community.general/plugins/modules/one_template.py

297 lines
8.7 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2021, Jyrki Gadinger <nilsding@nilsding.org>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
module: one_template
short_description: Manages OpenNebula templates
version_added: 2.4.0
requirements:
- pyone
description:
- Manages OpenNebula templates.
attributes:
check_mode:
support: partial
details:
- Note that check mode always returns C(changed=true) for existing templates, even if the template would not actually
change.
diff_mode:
support: none
options:
id:
description:
- A O(id) of the template you would like to manage. If not set then a new template will be created with the given O(name).
type: int
name:
description:
- A O(name) of the template you would like to manage. If a template with the given name does not exist it will be created,
otherwise it will be managed by this module.
type: str
template:
description:
- A string containing the template contents.
type: str
state:
description:
- V(present) - state that is used to manage the template.
- V(absent) - delete the template.
choices: ["present", "absent"]
default: present
type: str
filter:
description:
- V(user_primary_group) - Resources belonging to the user's primary group.
- V(user) - Resources belonging to the user.
- V(all) - All resources.
- V(user_groups) - Resources belonging to the user and any of his groups.
choices: [user_primary_group, user, all, user_groups]
default: user
type: str
version_added: 10.3.0
extends_documentation_fragment:
- community.general.opennebula
- community.general.attributes
author:
- "Jyrki Gadinger (@nilsding)"
"""
EXAMPLES = r"""
- name: Fetch the TEMPLATE by id
community.general.one_template:
id: 6459
register: result
- name: Print the TEMPLATE properties
ansible.builtin.debug:
var: result
- name: Fetch the TEMPLATE by name
community.general.one_template:
name: tf-prd-users-workerredis-p6379a
register: result
- name: Create a new or update an existing TEMPLATE
community.general.one_template:
name: generic-opensuse
template: |
CONTEXT = [
HOSTNAME = "generic-opensuse"
]
CPU = "1"
CUSTOM_ATTRIBUTE = ""
DISK = [
CACHE = "writeback",
DEV_PREFIX = "sd",
DISCARD = "unmap",
IMAGE = "opensuse-leap-15.2",
IMAGE_UNAME = "oneadmin",
IO = "threads",
SIZE = "" ]
MEMORY = "2048"
NIC = [
MODEL = "virtio",
NETWORK = "testnet",
NETWORK_UNAME = "oneadmin" ]
OS = [
ARCH = "x86_64",
BOOT = "disk0" ]
SCHED_REQUIREMENTS = "CLUSTER_ID=\\"100\\""
VCPU = "2"
- name: Delete the TEMPLATE by id
community.general.one_template:
id: 6459
state: absent
"""
RETURN = r"""
id:
description: Template ID.
type: int
returned: when O(state=present)
sample: 153
name:
description: Template name.
type: str
returned: when O(state=present)
sample: app1
template:
description: The parsed template.
type: dict
returned: when O(state=present)
group_id:
description: Template's group ID.
type: int
returned: when O(state=present)
sample: 1
group_name:
description: Template's group name.
type: str
returned: when O(state=present)
sample: one-users
owner_id:
description: Template's owner ID.
type: int
returned: when O(state=present)
sample: 143
owner_name:
description: Template's owner name.
type: str
returned: when O(state=present)
sample: ansible-test
"""
from ansible_collections.community.general.plugins.module_utils.opennebula import OpenNebulaModule
class TemplateModule(OpenNebulaModule):
def __init__(self):
argument_spec = dict(
id=dict(type='int', required=False),
name=dict(type='str', required=False),
state=dict(type='str', choices=['present', 'absent'], default='present'),
template=dict(type='str', required=False),
filter=dict(type='str', required=False, choices=['user_primary_group', 'user', 'all', 'user_groups'], default='user'),
)
mutually_exclusive = [
['id', 'name']
]
required_one_of = [('id', 'name')]
required_if = [
['state', 'present', ['template']]
]
OpenNebulaModule.__init__(self,
argument_spec,
supports_check_mode=True,
mutually_exclusive=mutually_exclusive,
required_one_of=required_one_of,
required_if=required_if)
def run(self, one, module, result):
params = module.params
id = params.get('id')
name = params.get('name')
desired_state = params.get('state')
template_data = params.get('template')
filter = params.get('filter')
self.result = {}
template = self.get_template_instance(id, name, filter)
needs_creation = False
if not template and desired_state != 'absent':
if id:
module.fail_json(msg="There is no template with id=" + str(id))
else:
needs_creation = True
if desired_state == 'absent':
self.result = self.delete_template(template)
else:
if needs_creation:
self.result = self.create_template(name, template_data, filter)
else:
self.result = self.update_template(template, template_data, filter)
self.exit()
def get_template(self, predicate, filter):
# filter was included, for discussions see:
# Issue: https://github.com/ansible-collections/community.general/issues/9278
# PR: https://github.com/ansible-collections/community.general/pull/9547
# the other two parameters are used for pagination, -1 for both essentially means "return all"
filter_values = {'user_primary_group': -4, 'user': -3, 'all': -2, 'user_groups': -1}
pool = self.one.templatepool.info(filter_values[filter], -1, -1)
for template in pool.VMTEMPLATE:
if predicate(template):
return template
return None
def get_template_by_id(self, template_id, filter):
return self.get_template(lambda template: (template.ID == template_id), filter)
def get_template_by_name(self, name, filter):
return self.get_template(lambda template: (template.NAME == name), filter)
def get_template_instance(self, requested_id, requested_name, filter):
if requested_id:
return self.get_template_by_id(requested_id, filter)
else:
return self.get_template_by_name(requested_name, filter)
def get_template_info(self, template):
info = {
'id': template.ID,
'name': template.NAME,
'template': template.TEMPLATE,
'user_name': template.UNAME,
'user_id': template.UID,
'group_name': template.GNAME,
'group_id': template.GID,
}
return info
def create_template(self, name, template_data, filter):
if not self.module.check_mode:
self.one.template.allocate("NAME = \"" + name + "\"\n" + template_data)
result = self.get_template_info(self.get_template_by_name(name, filter))
result['changed'] = True
return result
def update_template(self, template, template_data, filter):
if not self.module.check_mode:
# 0 = replace the whole template
self.one.template.update(template.ID, template_data, 0)
result = self.get_template_info(self.get_template_by_id(template.ID, filter))
if self.module.check_mode:
# Unfortunately it is not easy to detect if the template would have changed, therefore always report a change here.
result['changed'] = True
else:
# if the previous parsed template data is not equal to the updated one, this has changed
result['changed'] = template.TEMPLATE != result['template']
return result
def delete_template(self, template):
if not template:
return {'changed': False}
if not self.module.check_mode:
self.one.template.delete(template.ID)
return {'changed': True}
def main():
TemplateModule().run_module()
if __name__ == '__main__':
main()