Jakob Meng 1b38b7c500 Properly documented openstacksdk version requirements
With "extends_documentation_fragment: ['openstack.cloud.openstack']"
it is not necessary to list required Python libraries in section
'requirements' of DOCUMENTATION docstring in modules. Ansible will
merge requirements from doc fragments and DOCUMENTATION docstring
which previously resulted in duplicates such as in server module [0]:

* openstacksdk
* openstacksdk >= 0.36, < 0.99.0
* python >= 3.6

When removing the 'requirements' section from server module, then
Ansible will list openstacksdk once only:

* openstacksdk >= 0.36, < 0.99.0
* python >= 3.6

To see what documentation Ansible will produce for server module run:

  ansible-doc --type module openstack.cloud.server

[0] https://docs.ansible.com/ansible/latest/collections/openstack/\
    cloud/server_module.html

Change-Id: I727ed95ee480bb644b5a533f6a9526973677064c
2023-01-16 13:51:01 +01:00

563 lines
20 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright (c) 2018 Catalyst IT Ltd.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
DOCUMENTATION = r'''
---
module: coe_cluster_template
short_description: Manage COE cluster template in OpenStack Cloud
author: OpenStack Ansible SIG
description:
- Add or remove a COE (Container Orchestration Engine) cluster template
via OpenStack's Magnum aka Container Infrastructure Management API.
options:
coe:
description:
- The Container Orchestration Engine for this cluster template
- Required if I(state) is C(present).
choices: [kubernetes, swarm, mesos]
type: str
dns_nameserver:
description:
- The DNS nameserver address.
- Magnum's default value for I(dns_nameserver) is C(8.8.8.8).
type: str
docker_storage_driver:
description:
- Docker storage driver.
choices: [devicemapper, overlay, overlay2]
type: str
docker_volume_size:
description:
- The size in GB of the docker volume.
type: int
external_network_id:
description:
- The external network to attach to the cluster.
- When I(floating_ip_enabled) is set to C(true), then
I(external_network_id) must be defined.
type: str
fixed_network:
description:
- The fixed network name or id to attach to the cluster.
type: str
fixed_subnet:
description:
- The fixed subnet name or id to attach to the cluster.
type: str
flavor_id:
description:
- The flavor of the minion node for this cluster template.
type: str
floating_ip_enabled:
description:
- Indicates whether created clusters should have a floating ip or not.
- When I(floating_ip_enabled) is set to C(true), then
I(external_network_id) must be defined.
type: bool
default: true
keypair_id:
description:
- Name or ID of the keypair to use.
type: str
image_id:
description:
- Image id the cluster will be based on.
- Required if I(state) is C(present).
type: str
labels:
description:
- One or more key/value pairs.
type: raw
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: str
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: str
master_flavor_id:
description:
- The flavor of the master node for this cluster template.
type: str
master_lb_enabled:
description:
- Indicates whether created clusters should have a load balancer
for master nodes or not.
- Magnum's default value for I(master_lb_enabled) is C(true),
ours is C(false).
type: bool
default: false
name:
description:
- Name that has to be given to the cluster template.
required: true
type: str
network_driver:
description:
- The name of the driver used for instantiating container networks.
choices: [flannel, calico, docker]
type: str
no_proxy:
description:
- A comma separated list of IPs for which proxies should not be
used in the cluster.
type: str
public:
description:
- Indicates whether the cluster template is public or not.
- Magnum's default value for I(public) is C(false).
type: bool
registry_enabled:
description:
- Indicates whether the docker registry is enabled.
- Magnum's default value for I(registry_enabled) is C(false).
type: bool
server_type:
description:
- Server type for this cluster template.
- Magnum's default value for I(server_type) is C(vm).
choices: [vm, bm]
type: str
state:
description:
- Indicate desired state of the resource.
choices: [present, absent]
default: present
type: str
tls_disabled:
description:
- Indicates whether the TLS should be disabled.
- Magnum's default value for I(tls_disabled) is C(false).
type: bool
volume_driver:
description:
- The name of the driver used for instantiating container volumes.
choices: [cinder, rexray]
type: str
notes:
- Return values of this module are preliminary and will most likely change
when openstacksdk has finished its transition of cloud layer functions to
resource proxies.
extends_documentation_fragment:
- openstack.cloud.openstack
'''
# TODO: Update return values when coe related functions in openstacksdk
# have been ported to resource proxies.
RETURN = r'''
cluster_template:
description: Dictionary describing the template.
returned: On success when I(state) is C(present).
type: complex
contains:
apiserver_port:
description: The exposed port of COE API server.
type: int
cluster_distro:
description: Display the attribute os_distro defined as appropriate
metadata in image for the bay/cluster driver.
type: str
coe:
description: The Container Orchestration Engine for this cluster
template.
type: str
sample: kubernetes
created_at:
description: The date and time when the resource was created.
type: str
dns_nameserver:
description: The DNS nameserver address
type: str
sample: '8.8.8.8'
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: str
sample: public
fixed_network:
description: The fixed network name to attach to the cluster
type: str
sample: 07767ec6-85f5-44cb-bd63-242a8e7f0d9d
fixed_subnet:
description: The fixed subnet name to attach to the cluster.
type: str
sample: 05567ec6-85f5-44cb-bd63-242a8e7f0d9d
flavor_id:
description: The flavor of the minion node for this cluster template.
type: str
sample: c1.c1r1
floating_ip_enabled:
description: Indicates whether created clusters should have a
floating ip or not.
type: bool
sample: true
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: str
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: str
sample: https://10.0.0.10:8443
id:
description: The UUID of the cluster template.
type: str
image_id:
description: Image id the cluster will be based on.
type: str
sample: 05567ec6-85f5-44cb-bd63-242a8e7f0e9d
insecure_registry:
description: "The URL pointing to users's own private insecure docker
registry to deploy and run docker containers."
type: str
is_public:
description: Access to a baymodel/cluster template is normally limited to
the admin, owner or users within the same tenant as the
owners. Setting this flag makes the baymodel/cluster
template public and accessible by other users. The default
is not public.
type: bool
is_registry_enabled:
description: "Docker images by default are pulled from the public Docker
registry, but in some cases, users may want to use a
private registry. This option provides an alternative
registry based on the Registry V2: Magnum will create a
local registry in the bay/cluster backed by swift to host
the images. The default is to use the public registry."
type: bool
is_tls_disabled:
description: Transport Layer Security (TLS) is normally enabled to secure
the bay/cluster. In some cases, users may want to disable
TLS in the bay/cluster, for instance during development or
to troubleshoot certain problems. Specifying this parameter
will disable TLS so that users can access the COE endpoints
without a certificate. The default is TLS enabled.
type: bool
keypair_id:
description: Name or ID of the keypair to use.
type: str
sample: mykey
labels:
description: One or more key/value pairs.
type: dict
sample: {'key1': 'value1', 'key2': 'value2'}
location:
description: The OpenStack location of this resource.
type: str
master_flavor_id:
description: The flavor of the master node for this cluster template.
type: str
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: str
sample: k8scluster
network_driver:
description:
- The name of the driver used for instantiating container networks
type: str
sample: calico
no_proxy:
description: A comma separated list of IPs for which proxies should
not be used in the cluster.
type: str
sample: 10.0.0.4,10.0.0.5
properties:
description: Additional properties of the cluster template.
type: dict
sample: |
{
"docker_storage_driver": null,
"hidden": false,
"master_lb_enabled": false,
"project_id": "8fb245a1bd714d9a82e419f2b7bb69dd",
"tags": null,
"user_id": "51510ce12e294d5d9c7391bececcd1e8"
}
public:
description: Access to a baymodel/cluster template is normally limited
to the admin, owner or users within the same tenant as the
owners. Setting this flag makes the baymodel/cluster
template public and accessible by other users. The default
is not public.
type: bool
sample: false
registry_enabled:
description: "Docker images by default are pulled from the public Docker
registry, but in some cases, users may want to use a
private registry. This option provides an alternative
registry based on the Registry V2: Magnum will create a
local registry in the bay/cluster backed by swift to host
the images. The default is to use the public registry."
type: bool
sample: false
server_type:
description: Server type for this cluster template.
type: str
sample: vm
tls_disabled:
description: Transport Layer Security (TLS) is normally enabled to secure
the bay/cluster. In some cases, users may want to disable
TLS in the bay/cluster, for instance during development or
to troubleshoot certain problems. Specifying this parameter
will disable TLS so that users can access the COE endpoints
without a certificate. The default is TLS enabled.
type: bool
sample: false
updated_at:
description: The date and time when the resource was updated.
type: str
uuid:
description: The UUID of the cluster template.
type: str
volume_driver:
description: The name of the driver used for instantiating container
volumes.
type: str
sample: cinder
'''
EXAMPLES = r'''
- name: Create a new Kubernetes cluster template
openstack.cloud.coe_cluster_template:
cloud: devstack
coe: kubernetes
image_id: 2a8c9888-9054-4b06-a1ca-2bb61f9adb72
keypair_id: mykey
name: k8s
public: no
'''
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
class COEClusterTemplateModule(OpenStackModule):
argument_spec = dict(
coe=dict(choices=['kubernetes', 'swarm', 'mesos']),
dns_nameserver=dict(),
docker_storage_driver=dict(choices=['devicemapper', 'overlay',
'overlay2']),
docker_volume_size=dict(type='int'),
external_network_id=dict(),
fixed_network=dict(),
fixed_subnet=dict(),
flavor_id=dict(),
floating_ip_enabled=dict(type='bool', default=True),
http_proxy=dict(),
https_proxy=dict(),
image_id=dict(),
keypair_id=dict(),
labels=dict(type='raw'),
master_flavor_id=dict(),
master_lb_enabled=dict(type='bool', default=False),
name=dict(required=True),
network_driver=dict(choices=['flannel', 'calico', 'docker']),
no_proxy=dict(),
public=dict(type='bool'),
registry_enabled=dict(type='bool'),
server_type=dict(choices=['vm', 'bm']),
state=dict(default='present', choices=['absent', 'present']),
tls_disabled=dict(type='bool'),
volume_driver=dict(choices=['cinder', 'rexray']),
)
module_kwargs = dict(
required_if=[
('state', 'present', ('coe', 'image_id')),
],
supports_check_mode=True,
)
def run(self):
state = self.params['state']
cluster_template = self._find()
if self.ansible.check_mode:
self.exit_json(changed=self._will_change(state, cluster_template))
if state == 'present' and not cluster_template:
# Create cluster_template
cluster_template = self._create()
self.exit_json(
changed=True,
# TODO: Add .to_dict(computed=False) when Munch object has
# been replaced with openstacksdk resource object.
cluster_template=cluster_template)
elif state == 'present' and cluster_template:
# Update cluster_template
update = self._build_update(cluster_template)
if update:
cluster_template = self._update(cluster_template, update)
self.exit_json(
changed=bool(update),
# TODO: Add .to_dict(computed=False) when Munch object has
# been replaced with openstacksdk resource object.
cluster_template=cluster_template)
elif state == 'absent' and cluster_template:
# Delete cluster_template
self._delete(cluster_template)
self.exit_json(changed=True)
elif state == 'absent' and not cluster_template:
# Do nothing
self.exit_json(changed=False)
def _build_update(self, cluster_template):
update = {}
if self.params['floating_ip_enabled'] \
and self.params['external_network_id'] is None:
raise ValueError('floating_ip_enabled is True'
' but external_network_id is missing')
# TODO: Implement support for updates.
non_updateable_keys = [k for k in ['coe', 'dns_nameserver',
'docker_storage_driver',
'docker_volume_size',
'external_network_id',
'fixed_network',
'fixed_subnet', 'flavor_id',
'floating_ip_enabled',
'http_proxy', 'https_proxy',
'image_id', 'keypair_id',
'master_flavor_id',
'master_lb_enabled', 'name',
'network_driver', 'no_proxy',
'public', 'registry_enabled',
'server_type', 'tls_disabled',
'volume_driver']
if self.params[k] is not None
and k in cluster_template # drop when
# cluster_template got ported to resource proxy
and self.params[k] != cluster_template[k]]
labels = self.params['labels']
if labels is not None:
if isinstance(labels, str):
labels = dict([tuple(kv.split(":"))
for kv in labels.split(",")])
if labels != cluster_template['labels']:
non_updateable_keys.append('labels')
if non_updateable_keys:
self.fail_json(msg='Cannot update parameters {0}'
.format(non_updateable_keys))
attributes = dict((k, self.params[k])
for k in []
if self.params[k] is not None
and self.params[k] != cluster_template[k])
if attributes:
update['attributes'] = attributes
return update
def _create(self):
if self.params['floating_ip_enabled'] \
and self.params['external_network_id'] is None:
raise ValueError('floating_ip_enabled is True'
' but external_network_id is missing')
# TODO: Complement *_id parameters with find_* functions to allow
# specifying names in addition to IDs.
kwargs = dict((k, self.params[k])
for k in ['coe', 'dns_nameserver',
'docker_storage_driver', 'docker_volume_size',
'external_network_id', 'fixed_network',
'fixed_subnet', 'flavor_id',
'floating_ip_enabled', 'http_proxy',
'https_proxy', 'image_id', 'keypair_id',
'master_flavor_id', 'master_lb_enabled',
'name', 'network_driver', 'no_proxy', 'public',
'registry_enabled', 'server_type',
'tls_disabled', 'volume_driver']
if self.params[k] is not None)
labels = self.params['labels']
if labels is not None:
if isinstance(labels, str):
labels = dict([tuple(kv.split(":"))
for kv in labels.split(",")])
kwargs['labels'] = labels
# TODO: Replace with self.conn.container_infrastructure_management.\
# create_cluster_template() when available in openstacksdk.
return self.conn.create_cluster_template(**kwargs)
def _delete(self, cluster_template):
# TODO: Replace with self.conn.container_infrastructure_management.\
# delete_cluster_template() when available in openstacksdk.
self.conn.delete_cluster_template(cluster_template.name)
def _find(self):
name = self.params['name']
filters = {}
image_id = self.params['image_id']
if image_id is not None:
filters['image_id'] = image_id
coe = self.params['coe']
if coe is not None:
filters['coe'] = coe
# TODO: Replace with self.conn.container_infrastructure_management.\
# find_cluster_template() when available in openstacksdk.
return self.conn.get_cluster_template(name_or_id=name,
filters=filters,
detail=True)
def _update(self, cluster_template, update):
attributes = update.get('attributes')
if attributes:
# TODO: Implement support for updates.
# TODO: Replace with self.conn.\
# container_infrastructure_management.\
# update_cluster_template() when available in openstacksdk.
# cluster_template = self.conn.update_cluster_template(...)
pass
return cluster_template
def _will_change(self, state, cluster_template):
if state == 'present' and not cluster_template:
return True
elif state == 'present' and cluster_template:
return bool(self._build_update(cluster_template))
elif state == 'absent' and cluster_template:
return True
else:
# state == 'absent' and not cluster_template:
return False
def main():
module = COEClusterTemplateModule()
module()
if __name__ == "__main__":
main()