mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Previously LXD profiles were overwritten, now these are merged. (#1813)
* added ``merge_profile`` parameter to merge configurations from the play to an existing profile * add fragment * cosmetic changes Co-authored-by: Frank Dornheim <“dornheim@posteo.de@users.noreply.github.com”>
This commit is contained in:
parent
03fd6bd008
commit
6dd4cd0eb7
2 changed files with 121 additions and 5 deletions
2
changelogs/fragments/1813-lxd_profile-merge-profiles.yml
Normal file
2
changelogs/fragments/1813-lxd_profile-merge-profiles.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- lxd_profile - added ``merge_profile`` parameter to merge configurations from the play to an existing profile (https://github.com/ansible-collections/community.general/pull/1813).
|
|
@ -2,12 +2,12 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Copyright: (c) 2016, Hiroaki Nakamura <hnakamur@gmail.com>
|
# Copyright: (c) 2016, Hiroaki Nakamura <hnakamur@gmail.com>
|
||||||
|
# Copyright: (c) 2020, Frank Dornheim <dornheim@posteo.de>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# 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
|
from __future__ import absolute_import, division, print_function
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = '''
|
||||||
---
|
---
|
||||||
module: lxd_profile
|
module: lxd_profile
|
||||||
|
@ -52,6 +52,14 @@ options:
|
||||||
See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-11)
|
See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-11)
|
||||||
required: false
|
required: false
|
||||||
type: str
|
type: str
|
||||||
|
merge_profile:
|
||||||
|
description:
|
||||||
|
- Merge the configuration of the present profile with the new desired configuration,
|
||||||
|
instead of replacing it.
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
type: bool
|
||||||
|
version_added: 2.1.0
|
||||||
state:
|
state:
|
||||||
choices:
|
choices:
|
||||||
- present
|
- present
|
||||||
|
@ -142,6 +150,23 @@ EXAMPLES = '''
|
||||||
parent: br0
|
parent: br0
|
||||||
type: nic
|
type: nic
|
||||||
|
|
||||||
|
# An example for modify/merge a profile
|
||||||
|
- hosts: localhost
|
||||||
|
connection: local
|
||||||
|
tasks:
|
||||||
|
- name: Merge a profile
|
||||||
|
community.general.lxd_profile:
|
||||||
|
merge_profile: true
|
||||||
|
name: macvlan
|
||||||
|
state: present
|
||||||
|
config: {}
|
||||||
|
description: my macvlan profile
|
||||||
|
devices:
|
||||||
|
eth0:
|
||||||
|
nictype: macvlan
|
||||||
|
parent: br0
|
||||||
|
type: nic
|
||||||
|
|
||||||
# An example for deleting a profile
|
# An example for deleting a profile
|
||||||
- hosts: localhost
|
- hosts: localhost
|
||||||
connection: local
|
connection: local
|
||||||
|
@ -181,7 +206,6 @@ actions:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible_collections.community.general.plugins.module_utils.lxd import LXDClient, LXDClientException
|
from ansible_collections.community.general.plugins.module_utils.lxd import LXDClient, LXDClientException
|
||||||
|
|
||||||
|
@ -266,7 +290,7 @@ class LXDProfileManagement(object):
|
||||||
self._create_profile()
|
self._create_profile()
|
||||||
else:
|
else:
|
||||||
self.module.fail_json(
|
self.module.fail_json(
|
||||||
msg='new_name must not be set when the profile does not exist and the specified state is present',
|
msg='new_name must not be set when the profile does not exist and the state is present',
|
||||||
changed=False)
|
changed=False)
|
||||||
else:
|
else:
|
||||||
if self.new_name is not None and self.new_name != self.name:
|
if self.new_name is not None and self.new_name != self.name:
|
||||||
|
@ -307,10 +331,96 @@ class LXDProfileManagement(object):
|
||||||
self._needs_to_change_profile_config('devices')
|
self._needs_to_change_profile_config('devices')
|
||||||
)
|
)
|
||||||
|
|
||||||
def _apply_profile_configs(self):
|
def _merge_dicts(self, source, destination):
|
||||||
config = self.old_profile_json.copy()
|
"""Merge Dictionarys
|
||||||
|
|
||||||
|
Get a list of filehandle numbers from logger to be handed to
|
||||||
|
DaemonContext.files_preserve
|
||||||
|
|
||||||
|
Args:
|
||||||
|
dict(source): source dict
|
||||||
|
dict(destination): destination dict
|
||||||
|
Kwargs:
|
||||||
|
None
|
||||||
|
Raises:
|
||||||
|
None
|
||||||
|
Returns:
|
||||||
|
dict(destination): merged dict"""
|
||||||
|
for key, value in source.items():
|
||||||
|
if isinstance(value, dict):
|
||||||
|
# get node or create one
|
||||||
|
node = destination.setdefault(key, {})
|
||||||
|
self._merge_dicts(value, node)
|
||||||
|
else:
|
||||||
|
destination[key] = value
|
||||||
|
return destination
|
||||||
|
|
||||||
|
def _merge_config(self, config):
|
||||||
|
""" merge profile
|
||||||
|
|
||||||
|
Merge Configuration of the present profile and the new desired configitems
|
||||||
|
|
||||||
|
Args:
|
||||||
|
dict(config): Dict with the old config in 'metadata' and new config in 'config'
|
||||||
|
Kwargs:
|
||||||
|
None
|
||||||
|
Raises:
|
||||||
|
None
|
||||||
|
Returns:
|
||||||
|
dict(config): new config"""
|
||||||
|
# merge or copy the sections from the existing profile to 'config'
|
||||||
|
for item in ['config', 'description', 'devices', 'name', 'used_by']:
|
||||||
|
if item in config:
|
||||||
|
config[item] = self._merge_dicts(config['metadata'][item], config[item])
|
||||||
|
else:
|
||||||
|
config[item] = config['metadata'][item]
|
||||||
|
# merge or copy the sections from the ansible-task to 'config'
|
||||||
|
return self._merge_dicts(self.config, config)
|
||||||
|
|
||||||
|
def _generate_new_config(self, config):
|
||||||
|
""" rebuild profile
|
||||||
|
|
||||||
|
Rebuild the Profile by the configuration provided in the play.
|
||||||
|
Existing configurations are discarded.
|
||||||
|
|
||||||
|
This ist the default behavior.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
dict(config): Dict with the old config in 'metadata' and new config in 'config'
|
||||||
|
Kwargs:
|
||||||
|
None
|
||||||
|
Raises:
|
||||||
|
None
|
||||||
|
Returns:
|
||||||
|
dict(config): new config"""
|
||||||
for k, v in self.config.items():
|
for k, v in self.config.items():
|
||||||
config[k] = v
|
config[k] = v
|
||||||
|
return config
|
||||||
|
|
||||||
|
def _apply_profile_configs(self):
|
||||||
|
""" Selection of the procedure: rebuild or merge
|
||||||
|
|
||||||
|
The standard behavior is that all information not contained
|
||||||
|
in the play is discarded.
|
||||||
|
|
||||||
|
If "merge_profile" is provides in the play and "True", then existing
|
||||||
|
configurations from the profile and new ones defined are merged.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
None
|
||||||
|
Kwargs:
|
||||||
|
None
|
||||||
|
Raises:
|
||||||
|
None
|
||||||
|
Returns:
|
||||||
|
None"""
|
||||||
|
config = self.old_profile_json.copy()
|
||||||
|
if self.module.params['merge_profile']:
|
||||||
|
config = self._merge_config(config)
|
||||||
|
else:
|
||||||
|
config = self._generate_new_config(config)
|
||||||
|
|
||||||
|
# upload config to lxd
|
||||||
self.client.do('PUT', '/1.0/profiles/{0}'.format(self.name), config)
|
self.client.do('PUT', '/1.0/profiles/{0}'.format(self.name), config)
|
||||||
self.actions.append('apply_profile_configs')
|
self.actions.append('apply_profile_configs')
|
||||||
|
|
||||||
|
@ -371,6 +481,10 @@ def main():
|
||||||
devices=dict(
|
devices=dict(
|
||||||
type='dict',
|
type='dict',
|
||||||
),
|
),
|
||||||
|
merge_profile=dict(
|
||||||
|
type='bool',
|
||||||
|
default=False
|
||||||
|
),
|
||||||
state=dict(
|
state=dict(
|
||||||
choices=PROFILES_STATES,
|
choices=PROFILES_STATES,
|
||||||
default='present'
|
default='present'
|
||||||
|
|
Loading…
Reference in a new issue