Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cloudscale: new module cloudscale_server_group #54901

Merged
merged 3 commits into from
Apr 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
207 changes: 207 additions & 0 deletions lib/ansible/modules/cloud/cloudscale/cloudscale_server_group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2019, René Moser <mail@renemoser.net>
# 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: cloudscale_server_group
short_description: Manages server groups on the cloudscale.ch IaaS service
description:
- Create, update and remove server groups.
author:
- René Moser (@resmo)
version_added: '2.8'
options:
name:
description:
- Name of the server group.
- Either I(name) or I(uuid) is required. These options are mutually exclusive.
type: str
uuid:
description:
- UUID of the server group.
- Either I(name) or I(uuid) is required. These options are mutually exclusive.
type: str
type:
description:
- Type of the server group.
default: anti-affinity
type: str
state:
description:
- State of the server group.
choices: [ present, absent ]
default: present
type: str
extends_documentation_fragment: cloudscale
'''

EXAMPLES = '''
---
- name: Ensure server group exists
cloudscale_server_group:
name: my-name
type: anti-affinity
api_token: xxxxxx

- name: Ensure a server group is absent
cloudscale_server_group:
name: my-name
state: absent
api_token: xxxxxx
'''

RETURN = '''
---
href:
description: API URL to get details about this server group
returned: if available
type: str
sample: https://api.cloudscale.ch/v1/server-group/cfde831a-4e87-4a75-960f-89b0148aa2cc
uuid:
description: The unique identifier for this server
returned: always
type: str
sample: cfde831a-4e87-4a75-960f-89b0148aa2cc
name:
description: The display name of the server group
returned: always
type: str
sample: load balancers
type:
description: The type the server group
returned: if available
type: str
sample: anti-affinity
servers:
description: A list of servers that are part of the server group.
returned: if available
type: list
sample: []
state:
description: State of the server group.
returned: always
type: str
sample: present
'''

from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.cloudscale import AnsibleCloudscaleBase, cloudscale_argument_spec


class AnsibleCloudscaleServerGroup(AnsibleCloudscaleBase):

def __init__(self, module, namespace):
super(AnsibleCloudscaleServerGroup, self).__init__(module)
self._info = {}

def _init_container(self):
return {
'uuid': self._module.params.get('uuid') or self._info.get('uuid'),
'name': self._module.params.get('name') or self._info.get('name'),
'state': 'absent',
}

def _create_server_group(self, server_group):
self._module.fail_on_missing_params(['name'])
self._result['changed'] = True
data = {
'name': self._module.params.get('name'),
'type': self._module.params.get('type'),
}
if not self._module.check_mode:
server_group = self._post('server-groups', data)
return server_group

def _update_server_group(self, server_group):
data = {
'name': self._module.params.get('name'),
}
if server_group['name'] != data['name']:
self._result['changed'] = True

if not self._module.check_mode:
self._patch('server-groups/%s' % server_group['uuid'], data)
server_group = self.get_server_group()
return server_group

def get_server_group(self):
self._info = self._init_container()

uuid = self._info.get('uuid')
if uuid is not None:
server_group = self._get('server-groups/%s' % uuid)
if server_group:
self._info.update(server_group)
self._info.update(dict(state='present'))

else:
name = self._info.get('name')
matching_server_groups = []
for server_group in self._get('server-groups'):
if server_group['name'] == name:
matching_server_groups.append(server_group)

if len(matching_server_groups) > 1:
self._module.fail_json(msg="More than one server group with name exists: '%s'. "
"Use the 'uuid' parameter to identify the server group." % name)
elif len(matching_server_groups) == 1:
self._info.update(matching_server_groups[0])
self._info.update(dict(state='present'))
return self._info

def present_group(self):
server_group = self.get_server_group()
if server_group.get('state') == 'absent':
server_group = self._create_server_group(server_group)
else:
server_group = self._update_server_group(server_group)
return server_group

def absent_group(self):
server_group = self.get_server_group()
if server_group.get('state') != 'absent':
self._result['changed'] = True
if not self._module.check_mode:
self._delete('server-groups/%s' % server_group['uuid'])
return server_group


def main():
argument_spec = cloudscale_argument_spec()
argument_spec.update(dict(
name=dict(),
uuid=dict(),
type=dict(default='anti-affinity'),
state=dict(default='present', choices=['absent', 'present']),
))

module = AnsibleModule(
argument_spec=argument_spec,
required_one_of=(('name', 'uuid'),),
supports_check_mode=True,
)
cloudscale_server_group = AnsibleCloudscaleServerGroup(module, 'cloudscale_server_group')

if module.params['state'] == 'absent':
server_group = cloudscale_server_group.absent_group()
else:
server_group = cloudscale_server_group.present_group()

result = cloudscale_server_group.get_result(server_group)
module.exit_json(**result)


if __name__ == '__main__':
main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
- name: List all server groups
uri:
url: 'https://api.cloudscale.ch/v1/server-groups'
headers:
Authorization: 'Bearer {{ cloudscale_api_token }}'
status_code: 200
register: server_group_list

- name: Remove all server groups created by this test run
cloudscale_server_group:
uuid: '{{ item.uuid }}'
state: absent
when: cloudscale_resource_prefix in item.name
with_items: '{{ server_group_list.json }}'
loop_control:
label: '{{ item.name }} ({{ item.uuid }})'
2 changes: 2 additions & 0 deletions test/integration/targets/cloudscale_server_group/aliases
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cloud/cloudscale
unsupported
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
dependencies:
- cloudscale_common
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
- name: Fail missing params
cloudscale_server_group:
register: grp
ignore_errors: True
- name: 'VERIFY: Fail name and UUID'
assert:
that:
- grp is failed

- name: Create two server groups with the same name
uri:
url: 'https://api.cloudscale.ch/v1/server-groups'
method: POST
headers:
Authorization: 'Bearer {{ cloudscale_api_token }}'
body:
name: '{{ cloudscale_resource_prefix }}-duplicate'
type: 'anti-affinity'
body_format: json
status_code: 201
register: duplicate
with_sequence: count=2

- name: Try access to duplicate name
cloudscale_server_group:
name: '{{ cloudscale_resource_prefix }}-duplicate'
register: grp
ignore_errors: True
- name: 'VERIFY: Try access to duplicate name'
assert:
that:
- grp is failed
- grp.msg.startswith('More than one server group with name exists')

- name: Fail server group creation with UUID
cloudscale_server_group:
uuid: ea3b39a3-77a8-4d0b-881d-0bb00a1e7f48
register: grp
ignore_errors: True
- name: 'VERIFY: Fail server group creation with UUID'
assert:
that:
- grp is failed
- grp.msg.startswith('missing required arguments')
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
- block:
- import_tasks: failures.yml
- import_tasks: tests.yml
always:
- import_role:
name: cloudscale_common
tasks_from: cleanup_server_groups