Repository: ansible/ansible

Issue:
Support to operate OpenStack Magnum resources in ansible
SUMMARY
Support to operate OpenStack Magnum resources in ansible

ISSUE TYPE
Feature Idea
COMPONENT NAME

- [ ] os_coe_cluster_template
- [ ] os_coe_cluster
- [ ] os_coe_certificate

ANSIBLE VERSION
ansible 2.5.0
CONFIGURATION
N/A

OS / ENVIRONMENT
N/A

STEPS TO REPRODUCE
N/A

EXPECTED RESULTS
OpenStack Magnum related modules could be available in ansible.

ACTUAL RESULTS
There isn't any module related to OpenStack Magnum.


Discussion:

Resolving patch:
diff --git a/lib/ansible/modules/cloud/openstack/os_coe_cluster_template.py b/lib/ansible/modules/cloud/openstack/os_coe_cluster_template.py
new file mode 100644
--- /dev/null
+++ b/lib/ansible/modules/cloud/openstack/os_coe_cluster_template.py
@@ -0,0 +1,373 @@
+#!/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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+                    'status': ['preview'],
+                    'supported_by': 'community'}
+
+
+DOCUMENTATION = '''
+---
+module: os_coe_cluster_template
+short_description: Add/Remove COE cluster template from OpenStack Cloud
+extends_documentation_fragment: openstack
+version_added: "2.7"
+author: "Feilong Wang (@flwang)"
+description:
+   - Add or Remove COE cluster template from the OpenStack Container Infra
+     service.
+options:
+   availability_zone:
+     description:
+       - Ignored. Present for backwards compatibility
+   coe:
+     description:
+        - The Container Orchestration Engine for this clustertemplate
+     choices: [kubernetes, swarm, mesos]
+   dns_nameserver:
+      description:
+         - The DNS nameserver address
+      default: '8.8.8.8'
+   docker_storage_driver:
+      description:
+         - Docker storage driver
+      choices: [devicemapper, overlay]
+   docker_volume_size:
+      description:
+         - The size in GB of the docker volume
+   external_network_id:
+      description:
+         - The external network to attach to the Cluster
+   fixed_network:
+      description:
+         - The fixed network name to attach to the Cluster
+   fixed_subnet:
+      description:
+         - The fixed subnet name to attach to the Cluster
+   flavor_id:
+      description:
+         - The flavor of the minion node for this ClusterTemplate
+   floating_ip_enabled:
+      description:
+         - Indicates whether created clusters should have a floating ip or not
+      type: bool
+      default: 'yes'
+   keypair_id:
+      description:
+         - Name or ID of the keypair to use.
+   image_id:
+      description:
+         - Image id the cluster will be based on
+   labels:
+      description:
+         - One or more key/value pairs
+   http_proxy:
+      description:
+         - Address of a proxy that will receive all HTTP requests and relay them
+           The format is a URL including a port number
+   https_proxy:
+      description:
+         - Address of a proxy that will receive all HTTPS requests and relay
+           them. The format is a URL including a port number
+   master_flavor_id:
+      description:
+         - The flavor of the master node for this ClusterTemplate
+   master_lb_enabled:
+      description:
+         - Indicates whether created clusters should have a load balancer
+           for master nodes or not
+      type: bool
+      default: 'no'
+   name:
+      description:
+         - Name that has to be given to the cluster template
+      required: true
+   network_driver:
+      description:
+         - The name of the driver used for instantiating container networks
+      choices: [flannel, calico, docker]
+   no_proxy:
+      description:
+         - A comma separated list of IPs for which proxies should not be
+           used in the cluster
+   public:
+      description:
+         - Indicates whether the ClusterTemplate is public or not
+      type: bool
+      default: 'no'
+   registry_enabled:
+      description:
+         - Indicates whether the docker registry is enabled
+      type: bool
+      default: 'no'
+   server_type:
+      description:
+         - Server type for this ClusterTemplate
+      choices: [vm, bm]
+      default: vm
+   state:
+      description:
+         - Indicate desired state of the resource.
+      choices: [present, absent]
+      default: present
+   tls_disabled:
+      description:
+         - Indicates whether the TLS should be disabled
+      type: bool
+      default: 'no'
+   volume_driver:
+      description:
+         - The name of the driver used for instantiating container volumes
+      choices: [cinder, rexray]
+requirements: ["openstacksdk"]
+'''
+
+RETURN = '''
+id:
+    description: The cluster UUID.
+    returned: On success when I(state) is 'present'
+    type: string
+    sample: "39007a7e-ee4f-4d13-8283-b4da2e037c69"
+cluster_template:
+    description: Dictionary describing the template.
+    returned: On success when I(state) is 'present'
+    type: complex
+    contains:
+      coe:
+          description: The Container Orchestration Engine for this clustertemplate
+          type: string
+          sample: kubernetes
+      dns_nameserver:
+          description: The DNS nameserver address
+          type: string
+          sample: '8.8.8.8'
+      docker_storage_driver:
+          description: Docker storage driver
+          type: string
+          sample: devicemapper
+      docker_volume_size:
+          description: The size in GB of the docker volume
+          type: int
+          sample: 5
+      external_network_id:
+          description: The external network to attach to the Cluster
+          type: string
+          sample: public
+      fixed_network:
+          description: The fixed network name to attach to the Cluster
+          type: string
+          sample: 07767ec6-85f5-44cb-bd63-242a8e7f0d9d
+      fixed_subnet:
+          description:
+            - The fixed subnet name to attach to the Cluster
+          type: string
+          sample: 05567ec6-85f5-44cb-bd63-242a8e7f0d9d
+      flavor_id:
+          description:
+            - The flavor of the minion node for this ClusterTemplate
+          type: string
+          sample: c1.c1r1
+      floating_ip_enabled:
+          description:
+            - Indicates whether created clusters should have a floating ip or not
+          type: bool
+          default: true
+      keypair_id:
+          description:
+            - Name or ID of the keypair to use.
+          type: string
+          sample: mykey
+      image_id:
+          description:
+            - Image id the cluster will be based on
+          type: string
+          sample: 05567ec6-85f5-44cb-bd63-242a8e7f0e9d
+      labels:
+          description: One or more key/value pairs
+          type: dict
+          sample: {'key1': 'value1', 'key2': 'value2'}
+      http_proxy:
+          description:
+            - Address of a proxy that will receive all HTTP requests and relay them
+              The format is a URL including a port number
+          type: string
+          sample: http://10.0.0.11:9090
+      https_proxy:
+          description:
+            - Address of a proxy that will receive all HTTPS requests and relay
+              them. The format is a URL including a port number
+          type: string
+          sample: https://10.0.0.10:8443
+      master_flavor_id:
+          description:
+            - The flavor of the master node for this ClusterTemplate
+          type: string
+          sample: c1.c1r1
+      master_lb_enabled:
+          description:
+            - Indicates whether created clusters should have a load balancer
+              for master nodes or not
+          type: bool
+          sample: true
+      name:
+          description:
+            - Name that has to be given to the cluster template
+          type: string
+          sample: k8scluster
+      network_driver:
+          description:
+            - The name of the driver used for instantiating container networks
+          type: string
+          sample: calico
+      no_proxy:
+          description:
+            - A comma separated list of IPs for which proxies should not be
+              used in the cluster
+          type: string
+          sample: 10.0.0.4,10.0.0.5
+      public:
+          description:
+            - Indicates whether the ClusterTemplate is public or not
+          type: bool
+          sample: false
+      registry_enabled:
+          description:
+            - Indicates whether the docker registry is enabled
+          type: bool
+          sample: false
+      server_type:
+          description:
+            - Server type for this ClusterTemplate
+          type: string
+          sample: vm
+      tls_disabled:
+          description:
+            - Indicates whether the TLS should be disabled
+          type: bool
+          sample: false
+      volume_driver:
+          description:
+            - The name of the driver used for instantiating container volumes
+          type: string
+          sample: cinder
+'''
+
+EXAMPLES = '''
+# Create a new Kubernetes cluster template
+- os_coe_cluster_template:
+    name: k8s
+    coe: kubernetes
+    keypair_id: mykey
+    image_id: 2a8c9888-9054-4b06-a1ca-2bb61f9adb72
+    public: no
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.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(
+        coe=dict(required=True, choices=['kubernetes', 'swarm', 'mesos']),
+        dns_nameserver=dict(default='8.8.8.8'),
+        docker_storage_driver=dict(choices=['devicemapper', 'overlay']),
+        docker_volume_size=dict(type='int'),
+        external_network_id=dict(default=None),
+        fixed_network=dict(default=None),
+        fixed_subnet=dict(default=None),
+        flavor_id=dict(default=None),
+        floating_ip_enabled=dict(type='bool', default=True),
+        keypair_id=dict(default=None),
+        image_id=dict(required=True),
+        labels=dict(default=None, type='raw'),
+        http_proxy=dict(default=None),
+        https_proxy=dict(default=None),
+        master_lb_enabled=dict(type='bool', default=False),
+        master_flavor_id=dict(default=None),
+        name=dict(required=True),
+        network_driver=dict(choices=['flannel', 'calico', 'docker']),
+        no_proxy=dict(default=None),
+        public=dict(type='bool', default=False),
+        registry_enabled=dict(type='bool', default=False),
+        server_type=dict(default="vm", choices=['vm', 'bm']),
+        state=dict(default='present', choices=['absent', 'present']),
+        tls_disabled=dict(type='bool', default=False),
+        volume_driver=dict(choices=['cinder', 'rexray']),
+    )
+    module_kwargs = openstack_module_kwargs()
+    module = AnsibleModule(argument_spec, **module_kwargs)
+
+    params = module.params.copy()
+
+    state = module.params['state']
+    name = module.params['name']
+    coe = module.params['coe']
+    image_id = module.params['image_id']
+
+    kwargs = dict(
+        dns_nameserver=module.params['dns_nameserver'],
+        docker_storage_driver=module.params['docker_storage_driver'],
+        docker_volume_size=module.params['docker_volume_size'],
+        external_network_id=module.params['external_network_id'],
+        fixed_network=module.params['fixed_network'],
+        fixed_subnet=module.params['fixed_subnet'],
+        flavor_id=module.params['flavor_id'],
+        floating_ip_enabled=module.params['floating_ip_enabled'],
+        keypair_id=module.params['keypair_id'],
+        labels=_parse_labels(params['labels']),
+        http_proxy=module.params['http_proxy'],
+        https_proxy=module.params['https_proxy'],
+        master_lb_enabled=module.params['master_lb_enabled'],
+        master_flavor_id=module.params['master_flavor_id'],
+        network_driver=module.params['network_driver'],
+        no_proxy=module.params['no_proxy'],
+        public=module.params['public'],
+        registry_enabled=module.params['registry_enabled'],
+        server_type=module.params['server_type'],
+        tls_disabled=module.params['tls_disabled'],
+        volume_driver=module.params['volume_driver'],
+    )
+
+    sdk, cloud = openstack_cloud_from_module(module)
+    try:
+        changed = False
+        template = cloud.get_coe_cluster_template(name_or_id=name, filters={'coe': coe, 'image_id': image_id})
+
+        if state == 'present':
+            if not template:
+                template = cloud.create_coe_cluster_template(name, coe=coe, image_id=image_id, **kwargs)
+                changed = True
+            else:
+                changed = False
+
+            module.exit_json(changed=changed, cluster_template=template, id=template['uuid'])
+        elif state == 'absent':
+            if not template:
+                module.exit_json(changed=False)
+            else:
+                cloud.delete_coe_cluster_template(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()


Test patch: