diff --git a/lib/ansible/module_utils/network/f5/common.py b/lib/ansible/module_utils/network/f5/common.py index 1c2d175a344..3c5ee73984b 100644 --- a/lib/ansible/module_utils/network/f5/common.py +++ b/lib/ansible/module_utils/network/f5/common.py @@ -6,8 +6,10 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type +import copy import os import re +import datetime from ansible.module_utils._text import to_text from ansible.module_utils.basic import env_fallback @@ -26,6 +28,10 @@ except ImportError: HAS_F5SDK = False +MANAGED_BY_ANNOTATION_VERSION = 'f5-ansible.version' +MANAGED_BY_ANNOTATION_MODIFIED = 'f5-ansible.last_modified' + + f5_provider_spec = { 'server': dict( fallback=(env_fallback, ['F5_SERVER']) @@ -419,6 +425,56 @@ def on_bigip(): return False +def mark_managed_by(ansible_version, params): + metadata = [] + result = copy.deepcopy(params) + found1 = False + found2 = False + mark1 = dict( + name=MANAGED_BY_ANNOTATION_VERSION, + value=ansible_version, + persist='true' + ) + mark2 = dict( + name=MANAGED_BY_ANNOTATION_MODIFIED, + value=str(datetime.datetime.utcnow()), + persist='true' + ) + + if 'metadata' not in result: + result['metadata'] = [mark1, mark2] + return result + + for x in params['metadata']: + if x['name'] == MANAGED_BY_ANNOTATION_VERSION: + found1 = True + metadata.append(mark1) + if x['name'] == MANAGED_BY_ANNOTATION_MODIFIED: + found2 = True + metadata.append(mark1) + else: + metadata.append(x) + if not found1: + metadata.append(mark1) + if not found2: + metadata.append(mark2) + + result['metadata'] = metadata + return result + + +def only_has_managed_metadata(metadata): + managed = [ + MANAGED_BY_ANNOTATION_MODIFIED, + MANAGED_BY_ANNOTATION_VERSION, + ] + + for x in metadata: + if x['name'] not in managed: + return False + return True + + class Noop(object): """Represent no-operation required diff --git a/lib/ansible/modules/network/f5/bigip_virtual_server.py b/lib/ansible/modules/network/f5/bigip_virtual_server.py index aec54a19fa6..b625831704d 100644 --- a/lib/ansible/modules/network/f5/bigip_virtual_server.py +++ b/lib/ansible/modules/network/f5/bigip_virtual_server.py @@ -638,6 +638,8 @@ from collections import namedtuple try: from library.module_utils.network.f5.bigip import F5RestClient + from library.module_utils.network.f5.common import MANAGED_BY_ANNOTATION_VERSION + from library.module_utils.network.f5.common import MANAGED_BY_ANNOTATION_MODIFIED from library.module_utils.network.f5.common import F5ModuleError from library.module_utils.network.f5.common import AnsibleF5Parameters from library.module_utils.network.f5.common import cleanup_tokens @@ -646,11 +648,15 @@ try: from library.module_utils.network.f5.common import fail_json from library.module_utils.network.f5.common import exit_json from library.module_utils.network.f5.common import transform_name + from library.module_utils.network.f5.common import mark_managed_by + from library.module_utils.network.f5.common import only_has_managed_metadata from library.module_utils.network.f5.ipaddress import is_valid_ip from library.module_utils.network.f5.ipaddress import ip_interface from library.module_utils.network.f5.ipaddress import validate_ip_v6_address except ImportError: from ansible.module_utils.network.f5.bigip import F5RestClient + from ansible.module_utils.network.f5.common import MANAGED_BY_ANNOTATION_VERSION + from ansible.module_utils.network.f5.common import MANAGED_BY_ANNOTATION_MODIFIED from ansible.module_utils.network.f5.common import F5ModuleError from ansible.module_utils.network.f5.common import AnsibleF5Parameters from ansible.module_utils.network.f5.common import cleanup_tokens @@ -659,6 +665,8 @@ except ImportError: from ansible.module_utils.network.f5.common import fail_json from ansible.module_utils.network.f5.common import exit_json from ansible.module_utils.network.f5.common import transform_name + from ansible.module_utils.network.f5.common import mark_managed_by + from ansible.module_utils.network.f5.common import only_has_managed_metadata from ansible.module_utils.network.f5.ipaddress import is_valid_ip from ansible.module_utils.network.f5.ipaddress import ip_interface from ansible.module_utils.network.f5.ipaddress import validate_ip_v6_address @@ -1255,8 +1263,13 @@ class ApiParameters(Parameters): def metadata(self): if self._values['metadata'] is None: return None + if only_has_managed_metadata(self._values['metadata']): + return None result = [] for md in self._values['metadata']: + if md['name'] in [MANAGED_BY_ANNOTATION_VERSION, MANAGED_BY_ANNOTATION_MODIFIED]: + continue + tmp = dict(name=str(md['name'])) if 'value' in md: tmp['value'] = str(md['value']) @@ -2892,6 +2905,10 @@ class ModuleManager(object): def update_on_device(self): params = self.changes.api_params() + + # Mark the resource as managed by Ansible. + params = mark_managed_by(self.module.ansible_version, params) + uri = "https://{0}:{1}/mgmt/tm/ltm/virtual/{2}".format( self.client.provider['server'], self.client.provider['server_port'], @@ -2933,6 +2950,10 @@ class ModuleManager(object): params = self.changes.api_params() params['name'] = self.want.name params['partition'] = self.want.partition + + # Mark the resource as managed by Ansible. + params = mark_managed_by(self.module.ansible_version, params) + uri = "https://{0}:{1}/mgmt/tm/ltm/virtual/".format( self.client.provider['server'], self.client.provider['server_port']