自定义ansible模块

根据业务需要,需要自己写一些定制化ansible模块,网上这方面的资料挺少的。下面是一个操作rancher的模块

ANSIBLE_METADATA={
    'metadata_version': '1.1',
    'status': ['preview'],
    'supported_by': 'community'
}

DOCUMENTATION = '''
---
module: rancher

short_description: .

version_added: "2.4"

description:
    - ""

options:
    type:
        description:
            - project workspace 
        required: true
    json:
        description:
            - The variable WORKSPACE passed by Jenkins
        required: true

author:
    - Shuaibo (@shuaibo)
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.errors import AnsibleRuntimeError
import os, requests, json, time

result = dict(
    changed=False,
    version='',
    log=""
)


# 操作service函数
def service_opt(spacename, serivce, operation, json_data):
    global result
    base_url = "{0}{1}/workloads".format(os.getenv("RANCHER_URL", ""), os.getenv("RANCHER_PROJECT_ID", ""))
    headers = {
        'accept': 'application/json',
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + os.getenv("RANCHER_TOKEN", "")
    }
    url = base_url + '/deployment:' + spacename + ':' + serivce
    status_url = '{0}{1}/pods?sort=state&workloadId=deployment:'
    if operation == 'delete':
        response = requests.get(url, headers=headers, verify=False)
        r = json.loads(response.text)
        result['log'] += "开始删除:%s\n" % response.text
        # 检测是否删除成功
        for i in range(3):
            time.sleep(30)
            response = service_opt(spacename, serivce, 'query', json_data)
            result['log'] += "检查第%s次删除:%s\n" % (i + 1, response.text)
            if response['baseType'] == "error" and response['code'] == "NotFound" and response['status'] == 404:
                result['log'] += "检查第%s次删除:%s\n" % (i + 1, response.text)
                break
    elif operation == 'query':
        response = requests.get(url, headers=headers, verify=False)

        r = json.loads(response.text)
        for i in range(30):
            time.sleep(3)
    elif operation == "namespace":
        # 判断是否存在命名空间,不存在就创建
        namesapce_url = os.getenv("RANCHER_BASE_URL") + 'v3/cluster/%s/namespace' % os.getenv("RANCHER_CLUSTER_ID")
        response = requests.get(namesapce_url + '/' + os.getenv("RANCHER_NAMESPACEID"), headers=headers, verify=False)
        r = json.loads(response.text)
        if r.get('status') == 404:
            result['log'] = "命名空间不存在,创建命名空间"
            post_json = {"type": "namespace", "name": os.getenv("RANCHER_NAMESPACEID"),
                         "projectId": os.getenv("RANCHER_PROJECT_ID")}
            requests.post(namesapce_url, data=json.dumps(post_json), headers=headers, verify=False)
        else:
            result['log'] = "命名空间已存在,无操作"

    elif operation == 'create':
        response = requests.post(base_url[:-1], data=json.dumps(json_data), headers=headers, verify=False)
        result['log'] += "开始创建:%s\n" % response.text
        r = json.loads(response.text)
        if r.get('status') is not None:
            raise AnsibleRuntimeError("创建服务出错:\tURL:%s\t状态码:%s\t错误信息:%s" % (base_url[:-1], r['status'], response.text))
        for i in range(30):
            time.sleep(3)
            query_response = requests.get(url, headers=headers, verify=False)

            qr = json.loads(query_response.text)
            if qr.get('deploymentStatus') is None:
                raise AnsibleRuntimeError("创建服务出错:\t状态码:%s\t错误信息:%s" % (qr['status'], query_response.text))
            if qr['deploymentStatus']['availableReplicas'] == json_data['scale']:
                break
            result['log'] += "第%s次查询状态:%s\n" % (i + 1, query_response.text)



    elif operation == 'update':
        response = requests.put(url, data=json_data, headers=headers, verify=False)
        r = response.text
    elif operation == 'pod_status':
        url = status_url + spacename + ':' + serivce
        response = requests.get(url, headers=headers, verify=False)
        r = response.text
    else:
        rtn = '{"message": "arg:[%s] NOTFOUND", "status": 122, "code": "arg NOTFOUND", "type": "arg error"}' \
              % operation
        r = json.loads(rtn)
    try:
        return json.loads(r)
    except:
        return r


def run_module(module):
    global result
    json_data = {}
    with open(module.params['json']) as f:
        json_content = json.load(f)
        pts_service_name = json_content['name']
        pts_spacename = json_content['namespaceId']
        pts_scale = json_content['scale']
    service_opt(pts_spacename, pts_service_name, module.params['type'], json_content)

    module.exit_json(**result)


def main():
    module_args = dict(
        type=dict(type='str', required=True),
        json=dict(type='str', required=False),
    )

    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True
    )

    if module.check_mode:
        module.exit_json(**result)
    run_module(module)


if __name__ == '__main__':
    main()

写好之后随便找一个路径放进去。定义一个全局的环境变量

export ANSIBLE_LIBRARY="写好的py文件所在目录"

然后就可以用了

你可能感兴趣的:(DevOps)