Skip to content

Commit

Permalink
Make JSON lookups safer and fix crashes in check mode when instance i…
Browse files Browse the repository at this point in the history
…s absent
  • Loading branch information
InsanePrawn committed Jan 22, 2023
1 parent 97824c7 commit 0189f51
Showing 1 changed file with 22 additions and 15 deletions.
37 changes: 22 additions & 15 deletions plugins/modules/lxd_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,8 @@ def __init__(self, module):
self.trust_password = self.module.params.get('trust_password', None)
self.actions = []
self.diff = {'before': {}, 'after': {}}
self.old_instance_json = {}
self.old_sections = {}

def _build_config(self):
self.config = {}
Expand Down Expand Up @@ -576,10 +578,8 @@ def _unfreeze_instance(self):
def _instance_ipv4_addresses(self, ignore_devices=None):
ignore_devices = ['lo'] if ignore_devices is None else ignore_devices

resp_json = self._get_instance_state_json()
network = resp_json['metadata']['network'] or {}
network = dict((k, v) for k, v in network.items() if k not in ignore_devices) or {}
addresses = dict((k, [a['address'] for a in v['addresses'] if a['family'] == 'inet']) for k, v in network.items()) or {}
network = dict((k, v) for k, v in self._get_instance_state_json().get('metadata', {}).get('network', {}).items() if k not in ignore_devices)
addresses = dict((k, [a['address'] for a in v['addresses'] if a['family'] == 'inet']) for k, v in network.items())
return addresses

@staticmethod
Expand All @@ -592,7 +592,7 @@ def _get_addresses(self):
while datetime.datetime.now() < due:
time.sleep(1)
addresses = self._instance_ipv4_addresses()
if self._has_all_ipv4_addresses(addresses):
if self._has_all_ipv4_addresses(addresses) or self.module.check_mode:
self.addresses = addresses
return
except LXDClientException as e:
Expand Down Expand Up @@ -665,24 +665,25 @@ def _frozen(self):
def _needs_to_change_instance_config(self, key):
if key not in self.config:
return False

if key == 'config' and self.ignore_volatile_options: # the old behavior is to ignore configurations by keyword "volatile"
old_configs = dict((k, v) for k, v in self.old_instance_json['metadata'][key].items() if not k.startswith('volatile.'))
old_configs = dict((k, v) for k, v in self.old_sections.get(key, {}).items() if not k.startswith('volatile.'))
for k, v in self.config['config'].items():
if k not in old_configs:
return True
if old_configs[k] != v:
return True
return False
elif key == 'config': # next default behavior
old_configs = dict((k, v) for k, v in self.old_instance_json['metadata'][key].items())
old_configs = dict((k, v) for k, v in self.old_sections.get(key, {}).items())
for k, v in self.config['config'].items():
if k not in old_configs:
return True
if old_configs[k] != v:
return True
return False
else:
old_configs = self.old_instance_json['metadata'][key]
old_configs = self.old_sections.get(key, {})
return self.config[key] != old_configs

def _needs_to_apply_instance_configs(self):
Expand All @@ -692,7 +693,7 @@ def _needs_to_apply_instance_configs(self):
return False

def _apply_instance_configs(self):
old_metadata = copy.deepcopy(self.old_instance_json['metadata'])
old_metadata = copy.deepcopy(self.old_sections)
body_json = {}
for param in set(CONFIG_PARAMS) - set(CONFIG_CREATION_PARAMS):
if param in old_metadata:
Expand Down Expand Up @@ -720,17 +721,23 @@ def run(self):
self.client.authenticate(self.trust_password)
self.ignore_volatile_options = self.module.params.get('ignore_volatile_options')

self.diff['before']['state'] = self.old_state
self.diff['after']['state'] = self.state

old_sections = dict((k, v) for k, v in self.old_container_json['metadata'].items() if k in set(CONFIG_PARAMS) - set(CONFIG_CREATION_PARAMS))
self.diff['before']['instance'] = dict(
self.old_instance_json = self._get_instance_json()
self.old_sections = dict(
(section, content) if not isinstance(content, dict)
else (section, dict((k, v) for k, v in content.items()
if not (self.ignore_volatile_options and k.startswith('volatile.'))))
for section, content in old_sections.items()
for section, content in self.old_instance_json.get('metadata', {}).items()
if section in set(CONFIG_PARAMS) - set(CONFIG_CREATION_PARAMS)
)

self.diff['before']['instance'] = self.old_sections
# preliminary, will be overwritten in _apply_instance_configs() if called
self.diff['after']['instance'] = self.config

self.old_state = self._instance_json_to_module_state(self.old_instance_json)
self.diff['before']['state'] = self.old_state
self.diff['after']['state'] = self.state

action = getattr(self, LXD_ANSIBLE_STATES[self.state])
action()

Expand Down

0 comments on commit 0189f51

Please sign in to comment.