300 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			300 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
#!/usr/bin/python
 | 
						|
 | 
						|
# Copyright (c) 2018 Catalyst IT Ltd.
 | 
						|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
 | 
						|
 | 
						|
 | 
						|
ANSIBLE_METADATA = {'metadata_version': '1.1',
 | 
						|
                    'status': ['preview'],
 | 
						|
                    'supported_by': 'community'}
 | 
						|
 | 
						|
 | 
						|
DOCUMENTATION = '''
 | 
						|
---
 | 
						|
module: os_coe_cluster
 | 
						|
short_description: Add/Remove COE cluster from OpenStack Cloud
 | 
						|
author: "Feilong Wang (@flwang)"
 | 
						|
description:
 | 
						|
   - Add or Remove COE cluster from the OpenStack Container Infra service.
 | 
						|
options:
 | 
						|
   cluster_template_id:
 | 
						|
      description:
 | 
						|
         - The template ID of cluster template.
 | 
						|
      required: true
 | 
						|
      type: str
 | 
						|
   discovery_url:
 | 
						|
      description:
 | 
						|
         - Url used for cluster node discovery
 | 
						|
      type: str
 | 
						|
   docker_volume_size:
 | 
						|
      description:
 | 
						|
         - The size in GB of the docker volume
 | 
						|
      type: int
 | 
						|
   flavor_id:
 | 
						|
      description:
 | 
						|
         - The flavor of the minion node for this ClusterTemplate
 | 
						|
      type: str
 | 
						|
   keypair:
 | 
						|
      description:
 | 
						|
         - Name of the keypair to use.
 | 
						|
      type: str
 | 
						|
   labels:
 | 
						|
      description:
 | 
						|
         - One or more key/value pairs
 | 
						|
      type: raw
 | 
						|
   master_flavor_id:
 | 
						|
      description:
 | 
						|
         - The flavor of the master node for this ClusterTemplate
 | 
						|
      type: str
 | 
						|
   master_count:
 | 
						|
      description:
 | 
						|
         - The number of master nodes for this cluster
 | 
						|
      default: 1
 | 
						|
      type: int
 | 
						|
   name:
 | 
						|
      description:
 | 
						|
         - Name that has to be given to the cluster template
 | 
						|
      required: true
 | 
						|
      type: str
 | 
						|
   node_count:
 | 
						|
      description:
 | 
						|
         - The number of nodes for this cluster
 | 
						|
      default: 1
 | 
						|
      type: int
 | 
						|
   state:
 | 
						|
      description:
 | 
						|
         - Indicate desired state of the resource.
 | 
						|
      choices: [present, absent]
 | 
						|
      default: present
 | 
						|
      type: str
 | 
						|
   timeout:
 | 
						|
      description:
 | 
						|
         - Timeout for creating the cluster in minutes. Default to 60 mins
 | 
						|
           if not set
 | 
						|
      default: 60
 | 
						|
      type: int
 | 
						|
requirements:
 | 
						|
    - "python >= 3.6"
 | 
						|
    - "openstacksdk"
 | 
						|
 | 
						|
extends_documentation_fragment:
 | 
						|
- openstack.cloud.openstack
 | 
						|
'''
 | 
						|
 | 
						|
RETURN = '''
 | 
						|
id:
 | 
						|
    description: The cluster UUID.
 | 
						|
    returned: On success when I(state) is 'present'
 | 
						|
    type: str
 | 
						|
    sample: "39007a7e-ee4f-4d13-8283-b4da2e037c69"
 | 
						|
cluster:
 | 
						|
    description: Dictionary describing the cluster.
 | 
						|
    returned: On success when I(state) is 'present'
 | 
						|
    type: complex
 | 
						|
    contains:
 | 
						|
      api_address:
 | 
						|
          description:
 | 
						|
            - Api address of cluster master node
 | 
						|
          type: str
 | 
						|
          sample: https://172.24.4.30:6443
 | 
						|
      cluster_template_id:
 | 
						|
          description: The cluster_template UUID
 | 
						|
          type: str
 | 
						|
          sample: '7b1418c8-cea8-48fc-995d-52b66af9a9aa'
 | 
						|
      coe_version:
 | 
						|
          description:
 | 
						|
            - Version of the COE software currently running in this cluster
 | 
						|
          type: str
 | 
						|
          sample: v1.11.1
 | 
						|
      container_version:
 | 
						|
          description:
 | 
						|
            - "Version of the container software. Example: docker version."
 | 
						|
          type: str
 | 
						|
          sample: 1.12.6
 | 
						|
      created_at:
 | 
						|
          description:
 | 
						|
            - The time in UTC at which the cluster is created
 | 
						|
          type: str
 | 
						|
          sample: "2018-08-16T10:29:45+00:00"
 | 
						|
      create_timeout:
 | 
						|
          description:
 | 
						|
            - Timeout for creating the cluster in minutes. Default to 60 if
 | 
						|
              not set.
 | 
						|
          type: int
 | 
						|
          sample: 60
 | 
						|
      discovery_url:
 | 
						|
          description:
 | 
						|
            - Url used for cluster node discovery
 | 
						|
          type: str
 | 
						|
          sample: https://discovery.etcd.io/a42ee38e7113f31f4d6324f24367aae5
 | 
						|
      faults:
 | 
						|
          description:
 | 
						|
            - Fault info collected from the Heat resources of this cluster
 | 
						|
          type: dict
 | 
						|
          sample: {'0': 'ResourceInError: resources[0].resources...'}
 | 
						|
      flavor_id:
 | 
						|
          description:
 | 
						|
            - The flavor of the minion node for this cluster
 | 
						|
          type: str
 | 
						|
          sample: c1.c1r1
 | 
						|
      keypair:
 | 
						|
          description:
 | 
						|
            - Name of the keypair to use.
 | 
						|
          type: str
 | 
						|
          sample: mykey
 | 
						|
      labels:
 | 
						|
          description: One or more key/value pairs
 | 
						|
          type: dict
 | 
						|
          sample: {'key1': 'value1', 'key2': 'value2'}
 | 
						|
      master_addresses:
 | 
						|
          description:
 | 
						|
            - IP addresses of cluster master nodes
 | 
						|
          type: list
 | 
						|
          sample: ['172.24.4.5']
 | 
						|
      master_count:
 | 
						|
          description:
 | 
						|
            - The number of master nodes for this cluster.
 | 
						|
          type: int
 | 
						|
          sample: 1
 | 
						|
      master_flavor_id:
 | 
						|
          description:
 | 
						|
            - The flavor of the master node for this cluster
 | 
						|
          type: str
 | 
						|
          sample: c1.c1r1
 | 
						|
      name:
 | 
						|
          description:
 | 
						|
            - Name that has to be given to the cluster
 | 
						|
          type: str
 | 
						|
          sample: k8scluster
 | 
						|
      node_addresses:
 | 
						|
          description:
 | 
						|
            - IP addresses of cluster slave nodes
 | 
						|
          type: list
 | 
						|
          sample: ['172.24.4.8']
 | 
						|
      node_count:
 | 
						|
          description:
 | 
						|
            - The number of master nodes for this cluster.
 | 
						|
          type: int
 | 
						|
          sample: 1
 | 
						|
      stack_id:
 | 
						|
          description:
 | 
						|
            - Stack id of the Heat stack
 | 
						|
          type: str
 | 
						|
          sample: '07767ec6-85f5-44cb-bd63-242a8e7f0d9d'
 | 
						|
      status:
 | 
						|
          description: Status of the cluster from the heat stack
 | 
						|
          type: str
 | 
						|
          sample: 'CREATE_COMLETE'
 | 
						|
      status_reason:
 | 
						|
          description:
 | 
						|
            - Status reason of the cluster from the heat stack
 | 
						|
          type: str
 | 
						|
          sample: 'Stack CREATE completed successfully'
 | 
						|
      updated_at:
 | 
						|
          description:
 | 
						|
            - The time in UTC at which the cluster is updated
 | 
						|
          type: str
 | 
						|
          sample: '2018-08-16T10:39:25+00:00'
 | 
						|
      id:
 | 
						|
          description:
 | 
						|
            - Unique UUID for this cluster
 | 
						|
          type: str
 | 
						|
          sample: '86246a4d-a16c-4a58-9e96ad7719fe0f9d'
 | 
						|
'''
 | 
						|
 | 
						|
EXAMPLES = '''
 | 
						|
# Create a new Kubernetes cluster
 | 
						|
- os_coe_cluster:
 | 
						|
    name: k8s
 | 
						|
    cluster_template_id: k8s-ha
 | 
						|
    keypair: mykey
 | 
						|
    master_count: 3
 | 
						|
    node_count: 5
 | 
						|
'''
 | 
						|
 | 
						|
from ansible.module_utils.basic import AnsibleModule
 | 
						|
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
 | 
						|
                                                                                openstack_module_kwargs,
 | 
						|
                                                                                openstack_cloud_from_module)
 | 
						|
 | 
						|
 | 
						|
def _parse_labels(labels):
 | 
						|
    if isinstance(labels, str):
 | 
						|
        labels_dict = {}
 | 
						|
        for kv_str in labels.split(","):
 | 
						|
            k, v = kv_str.split("=")
 | 
						|
            labels_dict[k] = v
 | 
						|
        return labels_dict
 | 
						|
    if not labels:
 | 
						|
        return {}
 | 
						|
    return labels
 | 
						|
 | 
						|
 | 
						|
def main():
 | 
						|
    argument_spec = openstack_full_argument_spec(
 | 
						|
        cluster_template_id=dict(required=True),
 | 
						|
        discovery_url=dict(default=None),
 | 
						|
        docker_volume_size=dict(type='int'),
 | 
						|
        flavor_id=dict(default=None),
 | 
						|
        keypair=dict(default=None),
 | 
						|
        labels=dict(default=None, type='raw'),
 | 
						|
        master_count=dict(type='int', default=1),
 | 
						|
        master_flavor_id=dict(default=None),
 | 
						|
        name=dict(required=True),
 | 
						|
        node_count=dict(type='int', default=1),
 | 
						|
        state=dict(default='present', choices=['absent', 'present']),
 | 
						|
        timeout=dict(type='int', default=60),
 | 
						|
    )
 | 
						|
    module_kwargs = openstack_module_kwargs()
 | 
						|
    module = AnsibleModule(argument_spec, **module_kwargs)
 | 
						|
 | 
						|
    params = module.params.copy()
 | 
						|
 | 
						|
    state = module.params['state']
 | 
						|
    name = module.params['name']
 | 
						|
    cluster_template_id = module.params['cluster_template_id']
 | 
						|
 | 
						|
    kwargs = dict(
 | 
						|
        discovery_url=module.params['discovery_url'],
 | 
						|
        docker_volume_size=module.params['docker_volume_size'],
 | 
						|
        flavor_id=module.params['flavor_id'],
 | 
						|
        keypair=module.params['keypair'],
 | 
						|
        labels=_parse_labels(params['labels']),
 | 
						|
        master_count=module.params['master_count'],
 | 
						|
        master_flavor_id=module.params['master_flavor_id'],
 | 
						|
        node_count=module.params['node_count'],
 | 
						|
        create_timeout=module.params['timeout'],
 | 
						|
    )
 | 
						|
 | 
						|
    sdk, cloud = openstack_cloud_from_module(module)
 | 
						|
    try:
 | 
						|
        changed = False
 | 
						|
        cluster = cloud.get_coe_cluster(name_or_id=name, filters={'cluster_template_id': cluster_template_id})
 | 
						|
 | 
						|
        if state == 'present':
 | 
						|
            if not cluster:
 | 
						|
                cluster = cloud.create_coe_cluster(name, cluster_template_id=cluster_template_id, **kwargs)
 | 
						|
                changed = True
 | 
						|
            else:
 | 
						|
                changed = False
 | 
						|
 | 
						|
            # NOTE (brtknr): At present, create_coe_cluster request returns
 | 
						|
            # cluster_id as `uuid` whereas get_coe_cluster request returns the
 | 
						|
            # same field as `id`. This behaviour may change in the future
 | 
						|
            # therefore try `id` first then `uuid`.
 | 
						|
            cluster_id = cluster.get('id', cluster.get('uuid'))
 | 
						|
            cluster['id'] = cluster['uuid'] = cluster_id
 | 
						|
            module.exit_json(changed=changed, cluster=cluster, id=cluster_id)
 | 
						|
        elif state == 'absent':
 | 
						|
            if not cluster:
 | 
						|
                module.exit_json(changed=False)
 | 
						|
            else:
 | 
						|
                cloud.delete_coe_cluster(name)
 | 
						|
                module.exit_json(changed=True)
 | 
						|
    except sdk.exceptions.OpenStackCloudException as e:
 | 
						|
        module.fail_json(msg=str(e), extra_data=e.extra_data)
 | 
						|
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
    main()
 |