Skip to content

Commit

Permalink
Merge pull request #627 from HewlettPackard/SP_idempotent
Browse files Browse the repository at this point in the history
modified library files to achieve idempotency
  • Loading branch information
VenkateshRavula committed Jan 11, 2021
2 parents f52e198 + 1a8ebe4 commit da8cb7d
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 10 deletions.
20 changes: 15 additions & 5 deletions library/module_utils/oneview.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def dict_merge(original_resource_dict, data_dict):
return resource_dict


def merge_list_by_key(original_list, updated_list, key, ignore_when_null=None):
def merge_list_by_key(original_list, updated_list, key, ignore_when_null=None, replace_key=None, replace_value=None):
"""
Merge two lists by the key. It basically:
Expand Down Expand Up @@ -141,6 +141,8 @@ def merge_list_by_key(original_list, updated_list, key, ignore_when_null=None):
for ignored_key in ignore_when_null:
if ignored_key in item and item[ignored_key] is None:
item.pop(ignored_key)
if replace_key and item.get(replace_key) == replace_value:
item[replace_key] = items_map[item_key][replace_key]
merged_items[item_key] = items_map[item_key]
merged_items[item_key].update(item)
else:
Expand Down Expand Up @@ -932,10 +934,18 @@ def _merge_connections(self, merged_data, resource, data):
if data.get(SPKeys.CONNECTION_SETTINGS) and SPKeys.CONNECTIONS in data.get(SPKeys.CONNECTION_SETTINGS):
existing_connections = resource[SPKeys.CONNECTION_SETTINGS][SPKeys.CONNECTIONS]
params_connections = data[SPKeys.CONNECTION_SETTINGS][SPKeys.CONNECTIONS]
merged_data[SPKeys.CONNECTION_SETTINGS][SPKeys.CONNECTIONS] = merge_list_by_key(existing_connections, params_connections, key=SPKeys.ID)

merged_data[SPKeys.CONNECTION_SETTINGS] = self._merge_connections_boot(merged_data[SPKeys.CONNECTION_SETTINGS], resource[
SPKeys.CONNECTION_SETTINGS])
merged_data[SPKeys.CONNECTION_SETTINGS][SPKeys.CONNECTIONS] = merge_list_by_key(
existing_connections,
params_connections,
key=SPKeys.ID,
replace_key='portId',
replace_value='Auto'
)

merged_data[SPKeys.CONNECTION_SETTINGS] = self._merge_connections_boot(
merged_data[SPKeys.CONNECTION_SETTINGS],
resource[SPKeys.CONNECTION_SETTINGS]
)

if self._should_merge(data, resource, key=SPKeys.CONNECTIONS):
existing_connections = resource[SPKeys.CONNECTIONS]
Expand Down
8 changes: 7 additions & 1 deletion library/oneview_server_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,13 @@ def __present(self):

self.__validations_for_os_custom_attributes(merged_data, self.current_resource.data)

if not compare(self.current_resource.data, merged_data):
# removed the below fields as part of idempotency checks
updated_data = deepcopy(merged_data)
updated_data.pop('initialScopeUris', None)
if updated_data.get('firmware'):
updated_data['firmware'].pop('firmwareActivationType', None)

if not compare(self.current_resource.data, updated_data):
self.__update_server_profile(merged_data)
changed = True
msg = self.MSG_UPDATED
Expand Down
8 changes: 5 additions & 3 deletions library/oneview_server_profile_template.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
###
# Copyright (2016-2019) Hewlett Packard Enterprise Development LP
# Copyright (2016-2020) Hewlett Packard Enterprise Development LP
#
# Licensed under the Apache License, Version 2.0 (the "License");
# You may not use this file except in compliance with the License.
Expand Down Expand Up @@ -117,6 +117,7 @@
type: dict
'''

from copy import deepcopy
from ansible.module_utils.oneview import OneViewModule, ServerProfileReplaceNamesByUris, ServerProfileMerger, compare


Expand Down Expand Up @@ -193,8 +194,9 @@ def __create(self, data):

def __update(self, data):
merged_data = ServerProfileMerger().merge_data(self.current_resource.data, data)

equal = compare(merged_data, self.current_resource.data)
updated_data = deepcopy(merged_data)
updated_data.pop('initialScopeUris', None)
equal = compare(updated_data, self.current_resource.data)

if equal:
msg = self.MSG_ALREADY_PRESENT
Expand Down
48 changes: 47 additions & 1 deletion test/test_oneview_server_profile_template.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
###
# Copyright (2016-2019 Hewlett Packard Enterprise Development LP
# Copyright (2016-2020) Hewlett Packard Enterprise Development LP
#
# Licensed under the Apache License, Version 2.0 (the "License");
# You may not use this file except in compliance with the License.
Expand All @@ -28,12 +28,21 @@
SHT_URI = '/rest/server-hardware-types/94B55683-173F-4B36-8FA6-EC250BA2328B'
ENCLOSURE_GROUP_URI = '/rest/enclosure-groups/ad5e9e88-b858-4935-ba58-017d60a17c89'

CONNECTION_1 = {"connections": [{'id': 1, 'name': "connection-1", 'mac': "E2:4B:0D:30:00:29", 'portId': "Auto"}]}

BASIC_TEMPLATE = dict(
name=TEMPLATE_NAME,
serverHardwareTypeUri=SHT_URI,
enclosureGroupUri=ENCLOSURE_GROUP_URI
)

BASIC_TEMPLATE_WITH_CONNECTIONS = dict(
name=TEMPLATE_NAME,
serverHardwareTypeUri=SHT_URI,
enclosureGroupUri=ENCLOSURE_GROUP_URI,
connectionSettings=CONNECTION_1
)

BASIC_TEMPLATE_MODIFIED = dict(
name=TEMPLATE_NAME,
serverHardwareTypeUri=SHT_URI,
Expand All @@ -57,12 +66,35 @@
wwnType="Virtual"
)

CREATED_BASIC_TEMPLATE_WITH_CONNECTIONS = dict(
affinity="Bay",
bios=dict(manageBios=False, overriddenSettings=[]),
boot=dict(manageBoot=False, order=[]),
bootMode=dict(manageMode=False, mode=None, pxeBootPolicy=None),
category="server-profile-templates",
connectionSettings=CONNECTION_1,
enclosureGroupUri="/rest/enclosure-groups/ad5e9e88-b858-4935-ba58-017d60a17c89",
name="ProfileTemplate101",
serialNumberType="Virtual",
serverHardwareTypeUri="/rest/server-hardware-types/94B55683-173F-4B36-8FA6-EC250BA2328B",
status="OK",
type="ServerProfileTemplateV1",
uri="/rest/server-profile-templates/9a156b04-fce8-40b0-b0cd-92ced1311dda",
wwnType="Virtual"
)

PARAMS_FOR_PRESENT = dict(
config='config.json',
state='present',
data=BASIC_TEMPLATE
)

PARAMS_FOR_PRESENT_WITH_CONNECTIONS = dict(
config='config.json',
state='present',
data=BASIC_TEMPLATE_WITH_CONNECTIONS
)

PARAMS_FOR_UPDATE = dict(
config='config.json',
state='present',
Expand Down Expand Up @@ -119,6 +151,20 @@ def test_should_not_modify_when_template_already_exists(self):
ansible_facts=dict(server_profile_template=CREATED_BASIC_TEMPLATE)
)

def test_should_not_modify_connections_when_template_already_exists(self):
self.resource.data = CREATED_BASIC_TEMPLATE_WITH_CONNECTIONS
self.resource.create.return_value = CREATED_BASIC_TEMPLATE_WITH_CONNECTIONS

self.mock_ansible_module.params = PARAMS_FOR_PRESENT_WITH_CONNECTIONS

ServerProfileTemplateModule().run()

self.mock_ansible_module.exit_json.assert_called_once_with(
changed=False,
msg=ServerProfileTemplateModule.MSG_ALREADY_PRESENT,
ansible_facts=dict(server_profile_template=CREATED_BASIC_TEMPLATE_WITH_CONNECTIONS)
)

def test_should_update_when_data_has_modified_attributes(self):
self.resource.data = CREATED_BASIC_TEMPLATE
self.resource.update.return_value = CREATED_BASIC_TEMPLATE
Expand Down

0 comments on commit da8cb7d

Please sign in to comment.