diff --git a/CHANGELOG.md b/CHANGELOG.md index 946725e7d..27c5e9889 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,41 +1,5 @@ # Change Log -## v2.6.0 (2024-07-01) - -### FEATURE ENHANCEMENT - - Minimum supported Ansible core version to v2.15 - Ansible v2.15 EOL(https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html#ansible-community-changelogs) - -## v2.5.0 (2024-06-28) - -### NEW MODULES - - azure_rm_capacityreservationgroup: Add support for managed capacity reservation group ([#1557](https://github.com/ansible-collections/azure/pull/1557)) - - azure_rm_capacityreservationgroup_info: Add support for get capacity reservation group ([#1557](https://github.com/ansible-collections/azure/pull/1557)) - - azure_rm_networkwatcher: Add support for managed network watcher ([#1576](https://github.com/ansible-collections/azure/pull/1576)) - - azure_rm_networkwatcher_info: Add support for get network watcher facts ([#1576](https://github.com/ansible-collections/azure/pull/1576)) - - azure_rm_networkflowlogs: Add support for managed network flow logs ([#1576](https://github.com/ansible-collections/azure/pull/1576)) - - azure_rm_networkflowlogs_info: Add support for get network flow logs ([#1576](https://github.com/ansible-collections/azure/pull/1576)) - -### FEATURE ENHANCEMENT - - azure_rm_webapp: Add support for `identity` ([#1566](https://github.com/ansible-collections/azure/pull/1566)) - - azure_rm_webapp_info: Add support for `identity` ([#1566](https://github.com/ansible-collections/azure/pull/1566)) - - azure_rm_galleryimageversion: Allow creating gallery image versions from storage accounts ([#1466](https://github.com/ansible-collections/azure/pull/1466)) - - requirements.txt: - - Bump `azure-storage-blob` from 12.11.0 to 12.13.0 ([#1572](https://github.com/ansible-collections/azure/pull/1572)) - - Update `azure-cli-core` to 2.61.0 ([#1593](https://github.com/ansible-collections/azure/pull/1593)) - - Bump `azure-identity` from 1.14.0 to 1.16.1 ([#1596](https://github.com/ansible-collections/azure/pull/1596)) - - Limit `azure-iot-hub` to `x86_64 platforms` ([#1609](https://github.com/ansible-collections/azure/pull/1609)) - - azure_rm_containerinstance: Add support for `identity` ([#1581](https://github.com/ansible-collections/azure/pull/1581)) - - azure_rm_containerinstance_info: Add support for `identity` ([#1581](https://github.com/ansible-collections/azure/pull/1581)) - - azure_rm_storageaccount: Add support for `allow_shared_key_access` ([#1583](https://github.com/ansible-collections/azure/pull/1583)) - - azure_rm_virtualmachinescaleset: Add support for `identity` ([#1585](https://github.com/ansible-collections/azure/pull/1585)) - - azure_rm_virtualmachinescaleset_info: Add support for `identity` ([#1585](https://github.com/ansible-collections/azure/pull/1585)) - -### BUG FIXING - - azure_rm_webapp: Delete the imported logging module ([#1567](https://github.com/ansible-collections/azure/pull/1567)) - - azure_rm_postgresqlflexiblefirewallrule: Delete the imported logging module ([#1567](https://github.com/ansible-collections/azure/pull/1567)) - - azure_rm_adgroup_info: Return None if not a member of the group ([#1579](https://github.com/ansible-collections/azure/pull/1579)) - - ## v2.4.0 (2024-05-30) ### NEW MODULES diff --git a/README.md b/README.md index fdb0ac37d..196e4ee7a 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ It is recommended to run ansible in [Virtualenv](https://virtualenv.pypa.io/en/l ## Requirements -- ansible version >= 2.15 +- ansible version >= 2.14 To install Azure collection hosted in Galaxy: diff --git a/galaxy.yml b/galaxy.yml index 62541c7a7..cee906b98 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -9,7 +9,7 @@ namespace: azure name: azcollection # The version of the collection. Must be compatible with semantic versioning -version: 2.6.0 +version: 2.4.0 # The path to the Markdown (.md) readme file. This path is relative to the root of the collection readme: README.md diff --git a/meta/runtime.yml b/meta/runtime.yml index d8eeab9cf..a4f79f88b 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -14,6 +14,8 @@ action_groups: - azure.azcollection.azure_rm_adserviceprincipal_info - azure.azcollection.azure_rm_aduser - azure.azcollection.azure_rm_aduser_info + - azure.azcollection.azure_rm_afdorigin + - azure.azcollection.azure_rm_afdorigin_info - azure.azcollection.azure_rm_afdendpoint - azure.azcollection.azure_rm_afdendpoint_info - azure.azcollection.azure_rm_aks diff --git a/plugins/inventory/azure_rm.py b/plugins/inventory/azure_rm.py index 73d8ec7e7..0da9d4fcb 100644 --- a/plugins/inventory/azure_rm.py +++ b/plugins/inventory/azure_rm.py @@ -101,8 +101,8 @@ exclude_host_filters: # excludes hosts in the eastus region - location in ['eastus'] - - tags['tagkey'] is defined and tags['tagkey'] == 'tagvalue' - - tags['tagkey2'] is defined and tags['tagkey2'] == 'tagvalue2' + - tags['tagkey'] is defined and tags['tagkey'] == 'tagkey' + - tags['tagkey2'] is defined and tags['tagkey2'] == 'tagkey2' # excludes hosts that are powered off - powerstate != 'running' @@ -110,9 +110,9 @@ include_host_filters: # includes hosts that in the eastus region and power on - location in ['eastus'] and powerstate == 'running' - # includes hosts in the eastus region and power on OR includes hosts in the eastus2 region and tagkey value is tagvalue + # includes hosts in the eastus region and power on OR includes hosts in the eastus2 region and tagkey is tagkey - location in ['eastus'] and powerstate == 'running' - - location in ['eastus2'] and tags['tagkey'] is defined and tags['tagkey'] == 'tagvalue' + - location in ['eastus2'] and tags['tagkey'] is defined and tags['tagkey'] == 'tagkey' ''' # FUTURE: do we need a set of sane default filters, separate from the user-defineable ones? diff --git a/plugins/module_utils/azure_rm_common.py b/plugins/module_utils/azure_rm_common.py index fda5d818c..c747fc72c 100644 --- a/plugins/module_utils/azure_rm_common.py +++ b/plugins/module_utils/azure_rm_common.py @@ -700,8 +700,8 @@ def get_blob_service_client(self, resource_group_name, storage_account_name, aut try: self.log("Getting storage account detail") account = self.storage_client.storage_accounts.get_properties(resource_group_name=resource_group_name, account_name=storage_account_name) - if auth_mode == 'login' and self.azure_auth.credentials.get('credentials'): - credential = self.azure_auth.credentials['credentials'] + if auth_mode == 'login' and self.azure_auth.credentials.get('credential'): + credential = self.azure_auth.credentials['credential'] elif (auth_mode == 'login' and self.azure_auth.credentials.get('tenant') and self.azure_auth.credentials.get('client_id') and self.azure_auth.credentials.get('secret')): diff --git a/plugins/module_utils/azure_rm_common_ext.py b/plugins/module_utils/azure_rm_common_ext.py index ce1990b39..f95640582 100644 --- a/plugins/module_utils/azure_rm_common_ext.py +++ b/plugins/module_utils/azure_rm_common_ext.py @@ -13,50 +13,6 @@ class AzureRMModuleBaseExt(AzureRMModuleBase): - # This schema should be used when users can add more than one user assigned identity - # Also this schema allows the option to append identities in update - managed_identity_multiple_spec = dict( - type=dict( - type='str', - choices=['SystemAssigned', - 'UserAssigned', - 'SystemAssigned, UserAssigned', - 'None'], - default='None' - ), - user_assigned_identities=dict( - type='dict', - options=dict( - id=dict( - type='list', - default=[], - elements='str' - ), - append=dict( - type='bool', - default=True - ) - ), - default={} - ), - ) - - # This schema should be used when users can add only one user assigned identity - managed_identity_single_spec = dict( - type=dict( - type="str", - choices=[ - "SystemAssigned", - "UserAssigned", - "None" - ], - default="None" - ), - user_assigned_identity=dict( - type="str", - ), - ) - def inflate_parameters(self, spec, body, level): if isinstance(body, list): for item in body: @@ -257,61 +213,44 @@ def default_compare(self, modifiers, new, old, path, result): else: return True - def update_single_managed_identity(self, curr_identity, new_identity): - # Converting from single_managed_identity_spec to managed_identity_spec - new_identity = new_identity or dict() - new_identity_converted = { - 'type': new_identity.get('type', 'None'), - } - user_assigned_identity = new_identity.get('user_assigned_identity', None) - if user_assigned_identity is not None: - new_identity_converted['user_assigned_identities'] = { - 'id': [user_assigned_identity] - } - return self.update_managed_identity(curr_identity=curr_identity, new_identity=new_identity_converted, allow_identities_append=False) - - def update_managed_identity(self, curr_identity=None, new_identity=None, allow_identities_append=True): + def update_identities(self, curr_identity): curr_identity = curr_identity or dict() - # TODO need to remove self.module.params.get('identity', {}) - # after changing all modules to provide the "new_identity" parameter - # curr_identity and new_identity need to be mandatory parameters - new_identity = new_identity or self.module.params.get('identity', {}) or dict() - curr_managed_type = curr_identity.get('type', 'None') - new_managed_type = new_identity.get('type', 'None') - # If type set to None, and Resource has None, nothing to do - if new_managed_type == 'None' and curr_managed_type == 'None': - return False, None - changed = False + current_managed_type = curr_identity.get('type', 'None') + current_managed_identities = set(curr_identity.get('user_assigned_identities', {}).keys()) + param_identity = self.module.params.get('identity', {}) + param_identities = set(param_identity.get('user_assigned_identities', {}).get('id', [])) + external_identities = param_identities + + # If type set to None, and Resource has None, nothing to do + if 'None' in param_identity.get('type', 'None') and current_managed_type == 'None': + pass # If type set to None, and Resource has current identities, remove UserAssigned identities - # Or + elif param_identity.get('type', 'None') == 'None': + changed = True # If type in module args different from current type, update identities - if new_managed_type == 'None' or curr_managed_type != new_managed_type: + elif current_managed_type != param_identity.get('type', 'None'): changed = True - curr_user_assigned_identities = set(curr_identity.get('user_assigned_identities', {}).keys()) - new_user_assigned_identities = set(new_identity.get('user_assigned_identities', {}).get('id', [])) - result_user_assigned_identities = new_user_assigned_identities - # If type in module args contains 'UserAssigned' - if allow_identities_append and \ - 'UserAssigned' in new_managed_type and \ - new_identity.get('user_assigned_identities', {}).get('append', True) is True: - result_user_assigned_identities = new_user_assigned_identities.union(curr_user_assigned_identities) - - # Check if module args identities are different as current ones - if result_user_assigned_identities.difference(curr_user_assigned_identities) != set(): - changed = True + if 'UserAssigned' in param_identity.get('type', 'None'): + if param_identity.get('user_assigned_identities', {}).get('append', False) is True: + external_identities = param_identities.union(current_managed_identities) + if len(current_managed_identities) != len(external_identities): + # update identities + changed = True + # If new identities have to overwrite current identities + else: + # Check if module args identities are different as current ones + if current_managed_identities.difference(external_identities) != set(): + changed = True - result_identity = self.managed_identity['identity'](type=new_managed_type) + new_identity = self.managed_identity['identity'](type=param_identity.get('type')) # Append identities to the model - if len(result_user_assigned_identities) > 0: - result_identity.user_assigned_identities = {} - for identity in result_user_assigned_identities: - result_identity.user_assigned_identities[identity] = self.managed_identity['user_assigned']() - - return changed, result_identity + if external_identities: + new_identity.user_assigned_identities = {} + for identity in external_identities: + new_identity.user_assigned_identities[identity] = self.managed_identity['user_assigned']() - # TODO need to be removed after all modules changed to use the new name - update_identities = update_managed_identity + return changed, new_identity diff --git a/plugins/modules/azure_rm_adgroup_info.py b/plugins/modules/azure_rm_adgroup_info.py index 468a4a652..04393c02e 100644 --- a/plugins/modules/azure_rm_adgroup_info.py +++ b/plugins/modules/azure_rm_adgroup_info.py @@ -380,12 +380,9 @@ async def get_transitive_group_members(self, group_id, filters=None): ) if filters: request_configuration.query_parameters.filter = filters - try: - response = await self._client.groups.by_group_id(group_id).transitive_members.get( - request_configuration=request_configuration) - return response.value - except Exception: - return + response = await self._client.groups.by_group_id(group_id).transitive_members.get( + request_configuration=request_configuration) + return response.value async def get_raw_group_members(self, group_id, filters=None): request_configuration = GroupItemRequestBuilder.GroupItemRequestBuilderGetRequestConfiguration( diff --git a/plugins/modules/azure_rm_aduser.py b/plugins/modules/azure_rm_aduser.py index 139eb900d..e1c792649 100644 --- a/plugins/modules/azure_rm_aduser.py +++ b/plugins/modules/azure_rm_aduser.py @@ -75,17 +75,6 @@ - The password for the user. - Used when either creating or updating a user account. type: str - password_force_change: - description: - - Whether or not the user will be forced to change their password at next logon. - - If unspecified, Azure defaults this to true for new users. - - Used when either creating or updating a user account. - type: bool - password_force_change_mfa: - description: - - Identical behavior to password_force_change except multi-factor authentication (MFA) must be performed prior to changing the password. - - Used when either creating or updating a user account. - type: bool usage_location: description: - A two letter country code, ISO standard 3166. @@ -271,8 +260,6 @@ def __init__(self): account_enabled=dict(type='bool'), display_name=dict(type='str'), password_profile=dict(type='str', no_log=True), - password_force_change=dict(type='bool', no_log=False), - password_force_change_mfa=dict(type='bool', no_log=False), mail_nickname=dict(type='str'), on_premises_immutable_id=dict(type='str', aliases=['immutable_id']), usage_location=dict(type='str'), @@ -293,8 +280,6 @@ def __init__(self): self.account_enabled = None self.display_name = None self.password_profile = None - self.password_force_change = None - self.password_force_change_mfa = None self.mail_nickname = None self.on_premises_immutable_id = None self.usage_location = None @@ -342,11 +327,12 @@ def exec_module(self, **kwargs): if ad_user: # Update, changed - password_profile = PasswordProfile( - password=self.password_profile, - force_change_password_next_sign_in=self.password_force_change, - force_change_password_next_sign_in_with_mfa=self.password_force_change_mfa - ) + password = None + + if self.password_profile: + password = PasswordProfile( + password=self.password_profile, + ) should_update = False if self.on_premises_immutable_id and ad_user.on_premises_immutable_id != self.on_premises_immutable_id: @@ -363,11 +349,7 @@ def exec_module(self, **kwargs): should_update = True if should_update or self.display_name and ad_user.display_name != self.display_name: should_update = True - if should_update or self.password_profile is not None: - should_update = True - if should_update or self.password_force_change is not None: - should_update = True - if should_update or self.password_force_change_mfa is not None: + if should_update or password: should_update = True if should_update or self.user_principal_name and ad_user.user_principal_name != self.user_principal_name: should_update = True @@ -380,7 +362,7 @@ def exec_module(self, **kwargs): self.on_premises_extension_attributes_to_dict(ad_user.on_premises_extension_attributes) != self.on_premises_extension_attributes): should_update = True if should_update: - asyncio.get_event_loop().run_until_complete(self.update_user(ad_user, password_profile, extension_attributes)) + asyncio.get_event_loop().run_until_complete(self.update_user(ad_user, password, extension_attributes)) self.results['changed'] = True @@ -471,7 +453,7 @@ def to_dict(self, object): on_premises_extension_attributes=self.on_premises_extension_attributes_to_dict(object.on_premises_extension_attributes) ) - async def update_user(self, ad_user, password_profile, extension_attributes): + async def update_user(self, ad_user, password, extension_attributes): request_body = User( on_premises_immutable_id=self.on_premises_immutable_id, usage_location=self.usage_location, @@ -480,7 +462,7 @@ async def update_user(self, ad_user, password_profile, extension_attributes): user_type=self.user_type, account_enabled=self.account_enabled, display_name=self.display_name, - password_profile=password_profile, + password_profile=password, user_principal_name=self.user_principal_name, mail_nickname=self.mail_nickname, company_name=self.company_name, @@ -489,15 +471,13 @@ async def update_user(self, ad_user, password_profile, extension_attributes): return await self._client.users.by_user_id(ad_user.id).patch(body=request_body) async def create_user(self, extension_attributes): - password_profile = PasswordProfile( - password=self.password_profile, - force_change_password_next_sign_in=self.password_force_change, - force_change_password_next_sign_in_with_mfa=self.password_force_change_mfa + password = PasswordProfile( + password=self.password_profile ) request_body = User( account_enabled=self.account_enabled, display_name=self.display_name, - password_profile=password_profile, + password_profile=password, user_principal_name=self.user_principal_name, mail_nickname=self.mail_nickname, on_premises_immutable_id=self.on_premises_immutable_id, diff --git a/plugins/modules/azure_rm_afdendpoint.py b/plugins/modules/azure_rm_afdendpoint.py deleted file mode 100644 index c3fb9621d..000000000 --- a/plugins/modules/azure_rm_afdendpoint.py +++ /dev/null @@ -1,364 +0,0 @@ -#!/usr/bin/python -# -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -# -# Python SDK Reference: https://learn.microsoft.com/en-us/python/api/azure-mgmt-cdn/azure.mgmt.cdn.operations.afdendpointsoperations?view=azure-python -# -# TODO: Name check the URL -# -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - -DOCUMENTATION = ''' ---- -module: azure_rm_afdendpoint -version_added: "2.4.0" -short_description: Manage an Azure Front Door Endpoint to be used with Standard or Premium Frontdoor -description: - - Create, update and delete an Azure Front Door (AFD) Endpoint to be used by a Front Door Service Profile created using azure_rm_cdnprofile. - - This differs from the Front Door classic service and only is intended to be used by the Standard or Premium service offering. - -options: - auto_generated_domain_name_label_scope: - description: - - Indicates the endpoint name reuse scope. Cannot be used to update an existing Endpoint at this time. - default: TenantReuse - type: str - choices: - - TenantReuse - - SubscriptionReuse - - ResourceGroupReuse - - NoReuse - enabled_state: - description: - - Whether to enable use of this rule. - default: Enabled - type: str - choices: - - Enabled - - Disabled - location: - description: - - Valid Azure location. Defaults to location of the resource group. Cannot be used to update an existing Endpoint at this time. - type: str - name: - description: - - Name of the AFD Endpoint. - required: True - type: str - profile_name: - description: - - Name of the AFD Profile where the Endpoint will be attached to. - required: True - type: str - resource_group: - description: - - Name of a resource group where the Azure Front Door Endpoint exists or will be created. - required: True - type: str - state: - description: - - Assert the state of the AFD Endpoint. Use C(present) to create or update an AFD Endpoint and C(absent) to delete it. - default: present - type: str - choices: - - absent - - present - -extends_documentation_fragment: - - azure.azcollection.azure - - azure.azcollection.azure_tags - -author: - - Jarret Tooley (@jartoo) -''' - -EXAMPLES = ''' -- name: Create an AFD Endpoint - azure_rm_afdendpoint: - name: myEndpoint - profile_name: myProfile - resource_group: myResourceGroup - state: present - tags: - testing: testing - -- name: Delete the AFD Endpoint - azure_rm_afdendpoint: - name: myEndPoint - profile_name: myProfile - resource_group: myResourceGroup - state: absent -''' -RETURN = ''' -id: - description: - - ID of the AFD Endpoint. - returned: always - type: str - sample: "id: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/ - myResourceGroup/providers/Microsoft.Cdn/profiles/myProfile/endpoints/myEndpoint" -host_name: - description: - - Host name of the AFD Endpoint. - returned: always - type: str - sample: "myendpoint.azurefd.net" - -''' -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase - -try: - from azure.mgmt.cdn.models import AFDEndpoint, AFDEndpointUpdateParameters - from azure.mgmt.cdn import CdnManagementClient -except ImportError as ec: - # This is handled in azure_rm_common - pass - - -def endpoint_to_dict(endpoint): - return dict( - deployment_status=endpoint.deployment_status, - enabled_state=endpoint.enabled_state, - host_name=endpoint.host_name, - id=endpoint.id, - location=endpoint.location, - name=endpoint.name, - provisioning_state=endpoint.provisioning_state, - tags=endpoint.tags, - type=endpoint.type - ) - - -class AzureRMEndpoint(AzureRMModuleBase): - - def __init__(self): - self.module_arg_spec = dict( - auto_generated_domain_name_label_scope=dict( - type='str', - default='TenantReuse', - choices=["TenantReuse", "SubscriptionReuse", "ResourceGroupReuse", "NoReuse"] - ), - enabled_state=dict( - type='str', - default='Enabled', - choices=['Enabled', 'Disabled'] - ), - location=dict( - type='str' - ), - name=dict( - type='str', - required=True - ), - profile_name=dict( - type='str', - required=True - ), - resource_group=dict( - type='str', - required=True - ), - state=dict( - type='str', - default='present', - choices=['present', 'absent'] - ) - ) - - self.auto_generated_domain_name_label_scope = None - self.enabled_state = None - self.location = None - self.tags = None - - self.name = None - self.profile_name = None - self.resource_group = None - self.state = None - - self.endpoint_client = None - - self.results = dict(changed=False) - - super(AzureRMEndpoint, self).__init__( - derived_arg_spec=self.module_arg_spec, - supports_check_mode=True, - supports_tags=True) - - def exec_module(self, **kwargs): - """Main module execution method""" - - for key in list(self.module_arg_spec.keys()) + ['tags']: - setattr(self, key, kwargs[key]) - - self.endpoint_client = self.get_endpoint_client() - - to_be_updated = False - - if not self.location: - resource_group = self.get_resource_group(self.resource_group) - self.location = resource_group.location - - response = self.get_endpoint() - - if self.state == 'present': - - if not response: - self.log("Need to create the AFD Endpoint") - - if not self.check_mode: - new_response = self.create_endpoint() - self.results['id'] = new_response['id'] - self.results['host_name'] = new_response['host_name'] - self.log("AFD Endpoint creation done") - - self.results['changed'] = True - return self.results - - else: - self.log('Results : {0}'.format(response)) - self.results['id'] = response['id'] - self.results['host_name'] = response['host_name'] - - update_tags, self.tags = self.update_tags(response['tags']) - - if update_tags: - to_be_updated = True - - if response['provisioning_state'] == "Succeeded": - if response['enabled_state'] != self.enabled_state: - to_be_updated = True - - if self.location.lower() != response['location'].lower() and self.location: - # Location is not currently implemented in begin_update() - self.log("AFD Endpoint locations changes are not idempotent, please delete and recreate the Endpoint.") - - if to_be_updated: - self.log("Need to update the AFD Endpoint") - self.results['changed'] = True - - if not self.check_mode: - result = self.update_endpoint() - self.results['host_name'] = result['host_name'] - self.log("AFD Endpoint update done") - - elif self.state == 'absent': - if not response: - self.log("AFD Endpoint {0} does not exist.".format(self.name)) - self.results['id'] = "" - else: - self.log("Need to delete the AFD Endpoint") - self.results['changed'] = True - self.results['id'] = response['id'] - - if not self.check_mode: - self.delete_endpoint() - self.log("Azure AFD Endpoint deleted") - - return self.results - - def create_endpoint(self): - ''' - Creates an AFD Endpoint. - - :return: deserialized AFD Endpoint instance state dictionary - ''' - self.log("Creating the AFD Endpoint instance {0}".format(self.name)) - - parameters = AFDEndpoint( - auto_generated_domain_name_label_scope=self.auto_generated_domain_name_label_scope, - enabled_state=self.enabled_state, - location=self.location, - tags=self.tags - ) - - try: - poller = self.endpoint_client.afd_endpoints.begin_create( - endpoint_name=self.name, - profile_name=self.profile_name, - resource_group_name=self.resource_group, - endpoint=parameters) - response = self.get_poller_result(poller) - return endpoint_to_dict(response) - except Exception as exc: - self.log('Error attempting to create AFD Endpoint instance.') - self.fail("Error Creating AFD Endpoint instance: {0}".format(str(exc))) - - def update_endpoint(self): - ''' - Updates an AFD Endpoint. - - :return: deserialized AFD Endpoint instance state dictionary - ''' - self.log("Updating the AFD Endpoint instance {0}".format(self.name)) - - parameters = AFDEndpointUpdateParameters( - tags=self.tags, - enabled_state=self.enabled_state - ) - try: - poller = self.endpoint_client.afd_endpoints.begin_update( - endpoint_name=self.name, - profile_name=self.profile_name, - resource_group_name=self.resource_group, - endpoint_update_properties=parameters) - response = self.get_poller_result(poller) - return endpoint_to_dict(response) - except Exception as exc: - self.log('Error attempting to update AFD Endpoint instance.') - self.fail("Error updating AFD Endpoint instance: {0}".format(str(exc))) - - def delete_endpoint(self): - ''' - Deletes the specified AFD Endpoint in the specified subscription and resource group. - - :return: True - ''' - self.log("Deleting the AFD Endpoint {0}".format(self.name)) - try: - poller = self.endpoint_client.afd_endpoints.begin_delete( - resource_group_name=self.resource_group, profile_name=self.profile_name, endpoint_name=self.name) - self.get_poller_result(poller) - return True - except Exception as exc: - self.log('Error attempting to delete the AFD Endpoint.') - self.fail("Error deleting the AFD Endpoint: {0}".format(str(exc))) - return False - - def get_endpoint(self): - ''' - Gets the properties of the specified AFD Endpoint. - - :return: deserialized AFD Endpoint state dictionary - ''' - self.log( - "Checking if the AFD Endpoint {0} is present".format(self.name)) - try: - response = self.endpoint_client.afd_endpoints.get( - resource_group_name=self.resource_group, - profile_name=self.profile_name, - endpoint_name=self.name) - self.log("Response : {0}".format(response)) - self.log("AFD Endpoint : {0} found".format(response.name)) - return endpoint_to_dict(response) - except Exception as err: - self.log('Did not find the AFD Endpoint.') - return False - - def get_endpoint_client(self): - if not self.endpoint_client: - self.endpoint_client = self.get_mgmt_svc_client( - CdnManagementClient, - base_url=self._cloud_environment.endpoints.resource_manager, - api_version='2023-05-01') - return self.endpoint_client - - -def main(): - """Main execution""" - AzureRMEndpoint() - - -if __name__ == '__main__': - main() diff --git a/plugins/modules/azure_rm_afdendpoint_info.py b/plugins/modules/azure_rm_afdendpoint_info.py deleted file mode 100644 index b8865af0b..000000000 --- a/plugins/modules/azure_rm_afdendpoint_info.py +++ /dev/null @@ -1,271 +0,0 @@ -#!/usr/bin/python -# -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -# -# Python SDK Reference: https://learn.microsoft.com/en-us/python/api/azure-mgmt-cdn/azure.mgmt.cdn.operations.afdendpointsoperations?view=azure-python - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -DOCUMENTATION = ''' ---- -module: azure_rm_afdendpoint_info -version_added: "2.4.0" -short_description: Get Azure Front Door Endpoint facts to be used with Standard or Premium Frontdoor Service -description: - - Get facts for a specific Azure Front Door (AFD) Endpoint or all AFD Endpoints. - - This differs from the Front Door classic service and only is intended to be used by the Standard or Premium service offering. - -options: - resource_group: - description: - - Name of the resource group where this AFD Profile belongs. - required: true - type: str - profile_name: - description: - - Name of the AFD profile. - required: true - type: str - name: - description: - - Limit results to a specific AFD Endpoint. - type: str - tags: - description: - - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. - type: list - elements: str - -extends_documentation_fragment: - - azure.azcollection.azure - -author: - - Jarret Tooley (@jartoo) -''' - -EXAMPLES = ''' -- name: Get facts for all Endpoints in AFD Profile - azure_rm_afdendpoint_info: - resource_group: myResourceGroup - profile_name: myCDNProfile - tags: - - key - - key:value - -- name: Get facts of specific AFD Endpoint - azure_rm_afdendpoint_info: - resource_group: myResourceGroup - profile_name: myCDNProfile - name: myEndpoint1 -''' - -RETURN = ''' -afdendpoints: - description: List of AFD Endpoints. - returned: always - type: complex - contains: - auto_generated_domain_name_label_scope: - description: - - Indicates the endpoint name reuse scope. - type: str - sample: TenantReuse - deployment_status: - description: - - Current state of the resource. - type: str - sample: NotStarted - enabled_state: - description: - - Whether to enable use of this rule. - type: str - sample: Enabled - host_name: - description: - - The host name of the AFD Endpoint structured as endpointName.DNSZone. - type: str - sample: contoso.azureedge.net - id: - description: - - ID of the AFD Endpoint. - type: str - sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myCDN/providers/Microsoft.Cdn/profiles/myProf/endpoints/myEndpoint1" - location: - description: - - Location of the AFD Endpoint. - type: str - sample: Global - name: - description: - - Name of the AFD Endpoint. - returned: always - type: str - sample: myEndpoint - profile_name: - description: - - Name of the AFD Profile which holds the Endpoint. - returned: always - type: str - sample: myProfile - provisioning_state: - description: - - Provisioning status of the AFD Endpoint. - type: str - sample: Succeeded - resource_group: - description: - - Name of a resource group where the AFD Endpoint exists. - returned: always - type: str - sample: myResourceGroup - tags: - description: - - The tags of the AFD Endpoint. - type: list - sample: foo - type: - description: - - Resource type. - type: str - sample: Microsoft.Cdn/profiles/afdendpoints -''' - -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase - -try: - from azure.mgmt.cdn import CdnManagementClient -except ImportError: - # handled in azure_rm_common - pass - -import re - -AZURE_OBJECT_CLASS = 'AFDEndpoint' - - -class AzureRMAFDEndpointInfo(AzureRMModuleBase): - """Utility class to get Azure AFD Endpoint facts""" - - def __init__(self): - - self.module_args = dict( - name=dict(type='str'), - resource_group=dict( - type='str', - required=True - ), - profile_name=dict( - type='str', - required=True - ), - tags=dict( - type='list', - elements='str' - ) - ) - - self.results = dict( - changed=False, - afdendpoints=[] - ) - - self.name = None - self.resource_group = None - self.profile_name = None - self.tags = None - - super(AzureRMAFDEndpointInfo, self).__init__( - supports_check_mode=True, - derived_arg_spec=self.module_args, - supports_tags=False, - facts_module=True - ) - - def exec_module(self, **kwargs): - - for key in self.module_args: - setattr(self, key, kwargs[key]) - - self.endpoint_client = self.get_mgmt_svc_client( - CdnManagementClient, - base_url=self._cloud_environment.endpoints.resource_manager, - api_version='2023-05-01') - - if self.name: - self.results['afdendpoints'] = self.get_item() - else: - self.results['afdendpoints'] = self.list_by_profile() - - return self.results - - def get_item(self): - """Get a single Azure AFD Endpoint""" - - self.log('Get properties for {0}'.format(self.name)) - - item = None - result = [] - - try: - item = self.endpoint_client.afd_endpoints.get( - self.resource_group, self.profile_name, self.name) - except Exception: - pass - - if item and self.has_tags(item.tags, self.tags): - result = [self.serialize_afdendpoint(item)] - - return result - - def list_by_profile(self): - """Get all Azure AFD Endpoints within an AFD profile""" - - self.log('List all AFD Endpoints within an AFD profile') - - try: - response = self.endpoint_client.afd_endpoints.list_by_profile( - self.resource_group, self.profile_name) - except Exception as exc: - self.fail('Failed to list all items - {0}'.format(str(exc))) - - results = [] - for item in response: - if self.has_tags(item.tags, self.tags): - results.append(self.serialize_afdendpoint(item)) - - return results - - def serialize_afdendpoint(self, afdendpoint): - ''' - Convert a AFD Endpoint object to dict. - :param afdendpoint: AFD Endpoint object - :return: dict - ''' - result = self.serialize_obj(afdendpoint, AZURE_OBJECT_CLASS) - - new_result = {} - new_result['auto_generated_domain_name_label_scope'] = afdendpoint.auto_generated_domain_name_label_scope - new_result['deployment_status'] = afdendpoint.deployment_status - new_result['enabled_state'] = afdendpoint.enabled_state - new_result['host_name'] = afdendpoint.host_name - new_result['id'] = afdendpoint.id - new_result['location'] = afdendpoint.location - new_result['name'] = afdendpoint.name - new_result['profile_name'] = re.sub('\\/.*', '', re.sub('.*profiles\\/', '', result['id'])) - new_result['provisioning_state'] = afdendpoint.provisioning_state - new_result['resource_group'] = re.sub('\\/.*', '', re.sub('.*resourcegroups\\/', '', result['id'])) - new_result['tags'] = afdendpoint.tags - new_result['type'] = afdendpoint.type - return new_result - - -def main(): - """Main module execution code path""" - - AzureRMAFDEndpointInfo() - - -if __name__ == '__main__': - main() diff --git a/plugins/modules/azure_rm_afdorigin.py b/plugins/modules/azure_rm_afdorigin.py new file mode 100644 index 000000000..59c0f7f4d --- /dev/null +++ b/plugins/modules/azure_rm_afdorigin.py @@ -0,0 +1,515 @@ +#!/usr/bin/python +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Python SDK Reference: https://learn.microsoft.com/en-us/python/api/azure-mgmt-cdn/azure.mgmt.cdn.operations.afdoriginsoperations?view=azure-python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: azure_rm_afdorigin +version_added: "2.4.0" +short_description: Manage an Azure Front Door Origin to be used with Standard or Premium Frontdoor. +description: + - Create, update and delete an Azure Front Door (AFD) Origin to be used by a Front Door Service Profile created using azure_rm_cdnprofile. + +options: + azure_origin: + description: + - Resource reference to the AFD origin resource. + type: str + enabled_state: + description: + - Whether to enable health probes to be made against backends defined under backend pools. + - Health probes can only be disabled if there is a single enabled backend in single enabled backend pool. + type: str + choices: + - Enabled + - Disabled + host_name: + description: + - The address of the origin. Domain names, IPv4 addresses, and IPv6 addresses are supported. + - This should be unique across all origins in an endpoint. + type: str + http_port: + description: + - The value of the HTTP port. Must be between 1 and 65535. + default: 80 + type: int + https_port: + description: + - The value of the HTTPS port. Must be between 1 and 65535. + default: 443 + type: int + name: + description: + - Name of the origin that is unique within the AFD Profile. + required: true + type: str + origin_host_header: + description: + - The host header value sent to the origin with each request. If you leave this blank, the request hostname determines this value. + - Azure Front Door origins, such as Web Apps, Blob Storage, + - and Cloud Services require this host header value to match the origin hostname by default. + - This overrides the host header defined at the AFD Endpoint. + type: str + origin_group_name: + description: + - Name of the origin group which is unique within the profile. + required: true + type: str + priority: + description: + - Priority of origin in given origin group for load balancing. + - Higher priorities will not be used for load balancing if any lower priority origin is healthy. Must be between 1 and 5. + type: int + profile_name: + description: + - Name of the AFD Profile. + required: true + type: str + resource_group: + description: + - Name of a resource group where the AFD Origin exists or will be created. + required: true + type: str + shared_private_link_resource: + description: + - The properties of the private link resource for private origin. + type: dict + suboptions: + group_id: + description: + - The group id from the provider of resource the shared private link resource is for. + type: str + private_link: + description: + - The resource id of the resource the shared private link resource is for. + type: str + private_link_location: + description: + - The location of the shared private link resource. + type: str + request_message: + description: + - The request message for requesting approval of the shared private link resource. + type: str + status: + description: + - Status of the shared private link resource. Can be Pending, Approved, Rejected, Disconnected, or Timeout. + type: str + default: Approved + choices: + - Approved + - Disconnected + - Pending + - Rejected + - Timeout + state: + description: + - Assert the state of the AFD Profile. Use C(present) to create or update an AFD profile and C(absent) to delete it. + default: present + type: str + choices: + - absent + - present + weight: + description: + - Weight of the origin in given origin group for load balancing. Must be between 1 and 1000. + type: int + +extends_documentation_fragment: + - azure.azcollection.azure + +author: + - Jarret Tooley (@jartoo) +''' + +EXAMPLES = ''' +- name: Create an AFD Origin + azure_rm_afdorigin: + name: myOrigin + origin_group_name: myOriginGroup + profile_name: myProfile + resource_group: myResourceGroup + state: present + host_name: "10.0.0.1" + origin_host_header: "10.0.0.1" + http_port: 80 + https_port: 443 + priority: 1 + weight: 1000 + +- name: Delete an AFD Origin + azure_rm_afdorigin: + name: myOrigin + origin_group_name: myOriginGroup + profile_name: myProfile + resource_group: myResourceGroup + state: absent +''' +RETURN = ''' +id: + description: + - ID of the AFD Origin. + returned: always + type: str + sample: "id: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx/resourcegroups/myRG/providers/Microsoft.Cdn/profiles/myProf/origingroups/myOG/origins/myO" +host_name: + description: + - Host name of the AFD Origin. + returned: always + type: str + sample: "myorigin.azurefd.net" + +''' +import re +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase + + +try: + from azure.mgmt.cdn.models import AFDOrigin, AFDOriginUpdateParameters, SharedPrivateLinkResourceProperties, ResourceReference + from azure.mgmt.cdn import CdnManagementClient +except ImportError as ec: + # This is handled in azure_rm_common + pass + + +def origin_to_dict(origin): + ''' Convert object to dict ''' + return dict( + azure_origin=origin.azure_origin, + deployment_status=origin.deployment_status, + enabled_state=origin.enabled_state, + # enforce_certificate_check = origin.enforce_certificate_check, # Not fully implemented yet + host_name=origin.host_name, + http_port=origin.http_port, + https_port=origin.https_port, + id=origin.id, + name=origin.name, + origin_group_name=re.sub('\\/.*', '', re.sub('.*origingroups\\/', '', origin.id)), + origin_host_header=origin.origin_host_header, + priority=origin.priority, + provisioning_state=origin.provisioning_state, + shared_private_link_resource=origin.shared_private_link_resource, + type=origin.type, + weight=origin.weight + ) + + +class AzureRMOrigin(AzureRMModuleBase): + ''' Class for managing Origin ''' + def __init__(self): + self.module_arg_spec = dict( + azure_origin=dict(type='str'), + enabled_state=dict(type='str', choices=['Enabled', 'Disabled']), + # enforce_certification_name_check=dict(type='bool'), + host_name=dict(type='str'), + http_port=dict(type='int', default=80), + https_port=dict(type='int', default=443), + name=dict( + type='str', + required=True + ), + origin_group_name=dict( + type='str', + required=True + ), + origin_host_header=dict(type='str'), + priority=dict(type='int'), + profile_name=dict( + type='str', + required=True + ), + resource_group=dict( + type='str', + required=True + ), + shared_private_link_resource=dict( + type='dict', + options=dict( + group_id=dict(type='str'), + private_link=dict(type='str'), + private_link_location=dict(type='str'), + request_message=dict(type='str'), + status=dict( + type='str', + default='Approved', + choices=[ + "Pending", + "Approved", + "Rejected", + "Disconnected", + "Timeout" + ] + ) + ) + ), + state=dict( + type='str', + default='present', + choices=['present', 'absent'] + ), + weight=dict(type='int') + ) + + self.azure_origin = None + self.enabled_state = None + self.host_name = None + self.http_port = None + self.https_port = None + self.origin_host_header = None + self.priority = None + self.shared_private_link_resource = None + self.weight = None + + self.name = None + self.origin_group_name = None + self.profile_name = None + self.resource_group = None + self.state = None + + self.origin_client = None + + self.results = dict(changed=False) + + super(AzureRMOrigin, self).__init__( + derived_arg_spec=self.module_arg_spec, + supports_check_mode=True, + supports_tags=False) + + def exec_module(self, **kwargs): + """Main module execution method""" + + for key in list(self.module_arg_spec.keys()): + setattr(self, key, kwargs[key]) + + self.origin_client = self.get_origin_client() + + to_be_updated = False + + response = self.get_origin() + + if self.state == 'present': + + if not response: + self.log("Need to create the Origin") + + if not self.check_mode: + new_response = self.create_origin() + self.results['id'] = new_response['id'] + self.results['host_name'] = new_response['host_name'] + + self.results['changed'] = True + + else: + self.log('Results : {0}'.format(response)) + self.results['id'] = response['id'] + self.results['host_name'] = response['host_name'] + + if response['host_name'] != self.host_name and self.host_name: + to_be_updated = True + if response['http_port'] != self.http_port and self.http_port: + to_be_updated = True + if response['https_port'] != self.https_port and self.https_port: + to_be_updated = True + if response['origin_host_header'] != self.origin_host_header and self.origin_host_header: + to_be_updated = True + if response['priority'] != self.priority and self.priority: + to_be_updated = True + if response['weight'] != self.weight and self.weight: + to_be_updated = True + if response['enabled_state'] != self.enabled_state and self.enabled_state: + to_be_updated = True + if response['shared_private_link_resource'] != self.shared_private_link_resource and self.shared_private_link_resource: + to_be_updated = True + elif response['shared_private_link_resource']: + if response['shared_private_link_resource']['group_id'] != \ + self.shared_private_link_resource.get('group_id') and \ + self.shared_private_link_resource.get('group_id'): + to_be_updated = True + if response['shared_private_link_resource']['private_link'] != \ + self.shared_private_link_resource.get('private_link') and \ + self.shared_private_link_resource.get('private_link'): + to_be_updated = True + if response['shared_private_link_resource']['private_link_location'] != \ + self.shared_private_link_resource.get('private_link_location') and \ + self.shared_private_link_resource.get('private_link_location'): + to_be_updated = True + if response['shared_private_link_resource']['request_message'] != self.origin['shared_private_link_resource']['request_message'] and \ + self.shared_private_link_resource.get('request_message'): + to_be_updated = True + if response['shared_private_link_resource']['status'] != self.shared_private_link_resource.get('status') and \ + self.shared_private_link_resource.get('status'): + to_be_updated = True + + if to_be_updated: + self.log("Need to update the Origin") + + if not self.check_mode: + new_response = self.update_origin() + self.results['id'] = new_response['id'] + self.results['host_name'] = new_response['host_name'] + + self.results['changed'] = True + + elif self.state == 'absent': + if not response: + self.log("Origin {0} does not exist.".format(self.name)) + self.results['id'] = "" + self.results['host_name'] = "" + else: + self.log("Need to delete the Origin") + self.results['changed'] = True + self.results['id'] = response['id'] + self.results['host_name'] = response['host_name'] + + if not self.check_mode: + self.delete_origin() + + return self.results + + def create_origin(self): + ''' + Creates a Azure Origin. + + :return: deserialized Azure Origin instance state dictionary + ''' + self.log("Creating the Azure Origin instance {0}".format(self.name)) + + shared_private_link_resource = None + if self.shared_private_link_resource: + shared_private_link_resource = SharedPrivateLinkResourceProperties( + group_id=self.shared_private_link_resource.get('group_id'), + private_link=ResourceReference(id=self.shared_private_link_resource.get('private_link')), + private_link_location=self.shared_private_link_resource.get('private_link_location'), + request_message=self.shared_private_link_resource.get('request_message'), + status=self.shared_private_link_resource.get('status') + ) + + parameters = AFDOrigin( + azure_origin=self.azure_origin, + host_name=self.host_name, + http_port=self.http_port, + https_port=self.https_port, + origin_host_header=self.origin_host_header, + priority=self.priority, + weight=self.weight, + enabled_state=self.enabled_state, + shared_private_link_resource=shared_private_link_resource + ) + + try: + poller = self.origin_client.afd_origins.begin_create( + resource_group_name=self.resource_group, + profile_name=self.profile_name, + origin_group_name=self.origin_group_name, + origin_name=self.name, + origin=parameters) + response = self.get_poller_result(poller) + return origin_to_dict(response) + except Exception as exc: + self.log('Error attempting to create Azure Origin instance.') + self.fail("Error Creating Azure Origin instance: {0}".format(str(exc))) + + def update_origin(self): + ''' + Updates an Azure Origin. + + :return: deserialized Azure Origin instance state dictionary + ''' + self.log("Updating the Azure Origin instance {0}".format(self.name)) + + shared_private_link_resource = None + if self.shared_private_link_resource: + shared_private_link_resource = SharedPrivateLinkResourceProperties( + group_id=self.shared_private_link_resource.get('group_id'), + private_link=ResourceReference(id=self.shared_private_link_resource.get('private_link')), + private_link_location=self.shared_private_link_resource.get('private_link_location'), + request_message=self.shared_private_link_resource.get('request_message'), + status=self.shared_private_link_resource.get('status') + ) + + parameters = AFDOriginUpdateParameters( + azure_origin=self.azure_origin, + host_name=self.host_name, + http_port=self.http_port, + https_port=self.https_port, + origin_host_header=self.origin_host_header, + priority=self.priority, + weight=self.weight, + enabled_state=self.enabled_state, + shared_private_link_resource=shared_private_link_resource + ) + + try: + poller = self.origin_client.afd_origins.begin_update( + resource_group_name=self.resource_group, + profile_name=self.profile_name, + origin_group_name=self.origin_group_name, + origin_name=self.name, + origin_update_properties=parameters) + response = self.get_poller_result(poller) + return origin_to_dict(response) + except Exception as exc: + self.log('Error attempting to update Azure Origin instance.') + self.fail("Error updating Azure Origin instance: {0}".format(str(exc))) + + def delete_origin(self): + ''' + Deletes the specified Azure Origin in the specified subscription and resource group. + + :return: True + ''' + self.log("Deleting the Origin {0}".format(self.name)) + try: + poller = self.origin_client.afd_origins.begin_delete( + resource_group_name=self.resource_group, + profile_name=self.profile_name, + origin_group_name=self.origin_group_name, + origin_name=self.name) + self.get_poller_result(poller) + return True + except Exception as exc: + self.log('Error attempting to delete the Origin.') + self.fail("Error deleting the Origin: {0}".format(str(exc))) + return False + + def get_origin(self): + ''' + Gets the properties of the specified Origin. + + :return: deserialized Origin state dictionary + ''' + self.log( + "Checking if the Origin {0} is present".format(self.name)) + try: + response = self.origin_client.afd_origins.get( + resource_group_name=self.resource_group, + profile_name=self.profile_name, + origin_group_name=self.origin_group_name, + origin_name=self.name) + self.log("Response : {0}".format(response)) + self.log("Origin : {0} found".format(response.name)) + return origin_to_dict(response) + except Exception as exc: + self.log('Did not find the Origin. {0}'.format(str(exc))) + return False + + def get_origin_client(self): + ''' Set a reference to the Client ''' + if not self.origin_client: + self.origin_client = self.get_mgmt_svc_client( + CdnManagementClient, + base_url=self._cloud_environment.endpoints.resource_manager, + api_version='2023-05-01') + return self.origin_client + + +def main(): + """Main execution""" + AzureRMOrigin() + + +if __name__ == '__main__': + main() diff --git a/plugins/modules/azure_rm_afdorigin_info.py b/plugins/modules/azure_rm_afdorigin_info.py new file mode 100644 index 000000000..c2bce5425 --- /dev/null +++ b/plugins/modules/azure_rm_afdorigin_info.py @@ -0,0 +1,325 @@ +#!/usr/bin/python +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# +# Python SDK Reference: https://learn.microsoft.com/en-us/python/api/azure-mgmt-cdn/azure.mgmt.cdn.operations.afdoriginsoperations?view=azure-python +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: azure_rm_afdorigin_info +version_added: "2.4.0" +short_description: Get Azure Front Door Origin facts to be used with Standard or Premium Frontdoor Service +description: + - Get facts for a specific Azure Front Door (AFD) Origin or all AFD Origins. + - This differs from the Front Door classic service and only is intended to be used by the Standard or Premium service offering. + +options: + resource_group: + description: + - Name of the resource group where this AFD Profile belongs. + required: true + type: str + origin_group_name: + description: + - Name of the origin group which is unique within the profile. + required: true + type: str + profile_name: + description: + - Name of the AFD profile. + required: true + type: str + name: + description: + - Limit results to a specific AFD Origin. + type: str + +extends_documentation_fragment: + - azure.azcollection.azure + +author: + - Jarret Tooley (@jartoo) +''' + +EXAMPLES = ''' +- name: Get facts for all Origins in AFD Profile + azure_rm_afdorigin_info: + resource_group: myResourceGroup + profile_name: myCDNProfile + +- name: Get facts of specific AFD Origin + azure_rm_afdorigin_info: + name: myOrigin1 + profile_name: myCDNProfile + resource_group: myResourceGroup +''' + +RETURN = ''' +afdorigins: + description: List of AFD Origins. + returned: always + type: complex + contains: + azure_origin: + description: + - Resource reference to the AFD origin resource. + type: str + deployment_status: + description: + - Current state of the resource. + type: str + sample: NotStarted + enabled_state: + description: + - Whether to enable health probes to be made against backends defined under backend pools. + - Health probes can only be disabled if there is a single enabled backend in single enabled backend pool. + type: str + sample: Enabled + host_name: + description: + - The address of the origin. Domain names, IPv4 addresses, and IPv6 addresses are supported. + - This should be unique across all origins in an endpoint. + type: str + http_port: + description: + - The value of the HTTP port. Must be between 1 and 65535. + type: int + sample: 80 + https_port: + description: + - The value of the HTTPS port. Must be between 1 and 65535. + type: int + sample: 443 + id: + description: + - ID of the AFD Origin. + type: str + sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxx/resourcegroups/myRG/providers/Microsoft.Cdn/profiles/myProf/origingroups/myOG/origins/myO" + name: + description: + - Name of the AFD Origin. + type: str + origin_group_name: + description: + - Name of the origin group which is unique within the profile. + type: str + origin_host_header: + description: + - The host header value sent to the origin with each request. If you leave this blank, the request hostname determines this value. + - Azure Front Door origins, such as Web Apps, Blob Storage, and Cloud Services require this host header value to match the origin + - hostname by default. This overrides the host header defined at the AFD Endpoint. + type: str + priority: + description: + - Priority of origin in given origin group for load balancing. Higher priorities will not be used for load balancing if any + - lower priority origin is healthy. Must be between 1 and 5. + type: int + profile_name: + description: + - Name of the AFD Profile where the Origin will be added. + type: str + provisioning_state: + description: + - Provisioning status of the AFD Origin. + type: str + sample: Succeeded + resource_group: + description: + - Name of a resource group where the AFD Origin exists or will be created. + type: str + shared_private_link_resource: + description: + - The properties of the private link resource for private origin. + type: dict + contains: + group_id: + description: + - The group id from the provider of resource the shared private link resource is for. + type: str + private_link: + description: + - The resource id of the resource the shared private link resource is for. + type: str + private_link_location: + description: + - The location of the shared private link resource. + type: str + request_message: + description: + - The request message for requesting approval of the shared private link resource. + type: str + status: + description: + - Status of the shared private link resource. Can be Pending, Approved, Rejected, Disconnected, or Timeout. + type: str + sample: Approved + type: + description: + - Resource type. + type: str + sample: Microsoft.Cdn/profiles/origingroups/origins + weight: + description: + - Weight of the origin in given origin group for load balancing. Must be between 1 and 1000. + type: int +''' + +import re +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase + +try: + from azure.mgmt.cdn import CdnManagementClient +except ImportError: + # handled in azure_rm_common + pass + + +AZURE_OBJECT_CLASS = 'AFDOrigin' + + +class AzureRMAFDOriginInfo(AzureRMModuleBase): + """Utility class to get Azure AFD Origin facts""" + + def __init__(self): + + self.module_args = dict( + name=dict(type='str'), + origin_group_name=dict( + type='str', + required=True + ), + profile_name=dict( + type='str', + required=True + ), + resource_group=dict( + type='str', + required=True + ) + ) + + self.results = dict( + changed=False, + afdorigins=[] + ) + + self.name = None + self.origin_group_name = None + self.resource_group = None + self.profile_name = None + + super(AzureRMAFDOriginInfo, self).__init__( + supports_check_mode=True, + derived_arg_spec=self.module_args, + supports_tags=False, + facts_module=True + ) + + def exec_module(self, **kwargs): + + for key in self.module_args: + setattr(self, key, kwargs[key]) + + self.endpoint_client = self.get_mgmt_svc_client( + CdnManagementClient, + base_url=self._cloud_environment.endpoints.resource_manager, + api_version='2023-05-01') + + if self.name: + self.results['afdorigins'] = self.get_item() + else: + self.results['afdorigins'] = self.list_by_profile() + + return self.results + + def get_item(self): + """Get a single Azure AFD Origin""" + + self.log('Get properties for {0}'.format(self.name)) + + item = None + result = [] + + try: + item = self.endpoint_client.afd_origins.get( + resource_group_name=self.resource_group, profile_name=self.profile_name, origin_group_name=self.origin_group_name, origin_name=self.name) + except Exception as exc: + self.log("Did not find resource. {0}".format(str(exc))) + + if item: + result = [self.serialize_afdorigin(item)] + + return result + + def list_by_profile(self): + """Get all Azure AFD Origins within an AFD profile""" + + self.log('List all AFD Origins within an AFD profile') + + try: + response = self.endpoint_client.afd_origins.list_by_origin_group( + resource_group_name=self.resource_group, profile_name=self.profile_name, origin_group_name=self.origin_group_name) + except Exception as exc: + self.fail('Failed to list all origins. {0}'.format(str(exc))) + + results = [] + for item in response: + results.append(self.serialize_afdorigin(item)) + + return results + + def serialize_afdorigin(self, afdorigin): + ''' + Convert a AFD Origin object to dict. + :param afdorigin: AFD Origin object + :return: dict + ''' + result = self.serialize_obj(afdorigin, AZURE_OBJECT_CLASS) + + new_result = {} + new_result['azure_origin'] = afdorigin.azure_origin + new_result['deployment_status'] = afdorigin.deployment_status + new_result['enabled_state'] = afdorigin.enabled_state + new_result['host_name'] = afdorigin.host_name + new_result['http_port'] = afdorigin.http_port + new_result['https_port'] = afdorigin.https_port + new_result['https_port'] = afdorigin.https_port + new_result['id'] = afdorigin.id + new_result['name'] = afdorigin.name + new_result['origin_group_name'] = re.sub('\\/.*', '', re.sub('.*origingroups\\/', '', result['id'])) + new_result['origin_host_header'] = afdorigin.origin_host_header + new_result['priority'] = afdorigin.priority + new_result['provisioning_state'] = afdorigin.provisioning_state + new_result['priority'] = afdorigin.priority + new_result['profile_name'] = re.sub('\\/.*', '', re.sub('.*profiles\\/', '', result['id'])) + new_result['resource_group'] = re.sub('\\/.*', '', re.sub('.*resourcegroups\\/', '', result['id'])) + new_result['shared_private_link_resource'] = dict() + if afdorigin.shared_private_link_resource: + new_result['shared_private_link_resource']['group_id'] = afdorigin.shared_private_link_resource.group_id + new_result['shared_private_link_resource']['private_link'] = afdorigin.shared_private_link_resource.private_link + new_result['shared_private_link_resource']['private_link_location'] = afdorigin.shared_private_link_resource.private_link_location + new_result['shared_private_link_resource']['request_message'] = afdorigin.shared_private_link_resource.request_message + new_result['shared_private_link_resource']['status'] = afdorigin.shared_private_link_resource.status + else: + new_result['shared_private_link_resource']['group_id'] = None + new_result['shared_private_link_resource']['private_link'] = None + new_result['shared_private_link_resource']['private_link_location'] = None + new_result['shared_private_link_resource']['request_message'] = None + new_result['shared_private_link_resource']['status'] = None + new_result['type'] = afdorigin.type + new_result['weight'] = afdorigin.weight + return new_result + + +def main(): + """Main module execution code path""" + AzureRMAFDOriginInfo() + + +if __name__ == '__main__': + main() diff --git a/plugins/modules/azure_rm_appgateway.py b/plugins/modules/azure_rm_appgateway.py index 1d1defacf..8d70dda89 100644 --- a/plugins/modules/azure_rm_appgateway.py +++ b/plugins/modules/azure_rm_appgateway.py @@ -872,42 +872,6 @@ description: - The version of the rule set type. type: str - identity: - description: - - Identity for the App Gateway - type: dict - version_added: '2.5.0' - suboptions: - type: - description: - - Type of the managed identity - choices: - - SystemAssigned - - UserAssigned - - SystemAssigned, UserAssigned - - None - default: None - type: str - user_assigned_identities: - description: - - User Assigned Managed Identities and its options - required: false - type: dict - default: {} - suboptions: - id: - description: - - List of the user assigned identities IDs associated to the App Gateway - required: false - type: list - elements: str - default: [] - append: - description: - - If the list of identities has to be appended to current identities (true) or if it has to replace current identities (false) - required: false - type: bool - default: True gateway_state: description: - Start or Stop the application gateway. When specified, no updates will occur to the gateway. @@ -1574,18 +1538,16 @@ ''' import time +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from copy import deepcopy -import json -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_rest import GenericRestClient -from ansible.module_utils.common.dict_transformations import _snake_to_camel -from ansible.module_utils.six.moves.collections_abc import MutableMapping +from ansible.module_utils.common.dict_transformations import ( + _snake_to_camel, dict_merge, recursive_diff, +) try: from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller from azure.mgmt.core.tools import parse_resource_id, is_valid_resource_id - from azure.mgmt.network.models import ManagedServiceIdentity except ImportError: # This is handled in azure_rm_common pass @@ -1762,36 +1724,7 @@ class Actions: ) -user_assigned_identities_spec = dict( - id=dict( - type='list', - default=[], - elements='str' - ), - append=dict( - type='bool', - default=True - ) -) - -managed_identity_spec = dict( - type=dict( - type='str', - choices=['SystemAssigned', - 'UserAssigned', - 'SystemAssigned, UserAssigned', - 'None'], - default='None' - ), - user_assigned_identities=dict( - type='dict', - options=user_assigned_identities_spec, - default={} - ), -) - - -class AzureRMApplicationGateways(AzureRMModuleBaseExt): +class AzureRMApplicationGateways(AzureRMModuleBase): """Configuration class for an Azure RM Application Gateway resource""" def __init__(self): @@ -1986,10 +1919,6 @@ def __init__(self): type='bool', default=False ), - identity=dict( - type='dict', - options=managed_identity_spec - ), gateway_state=dict( type='str', choices=['started', 'stopped'], @@ -2009,21 +1938,11 @@ def __init__(self): self.state = None self.gateway_state = None self.to_do = Actions.NoAction - self.identity = None - self._managed_identity = None super(AzureRMApplicationGateways, self).__init__(derived_arg_spec=self.module_arg_spec, supports_check_mode=True, supports_tags=True) - @property - def managed_identity(self): - if not self._managed_identity: - self._managed_identity = {"identity": ManagedServiceIdentity, - "user_assigned": dict - } - return self._managed_identity - def exec_module(self, **kwargs): """Main module execution method""" for key in list(self.module_arg_spec.keys()) + ['tags']: @@ -2398,9 +2317,6 @@ def exec_module(self, **kwargs): response = None - self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - base_url=self._cloud_environment.endpoints.resource_manager) - resource_group = self.get_resource_group(self.resource_group) if "location" not in self.parameters: @@ -2408,13 +2324,6 @@ def exec_module(self, **kwargs): old_response = self.get_applicationgateway() - properties = self.get_resource() - old_ssl_certs = [] - if properties: - for old_cert in properties.get('properties', {}).get('sslCertificates', []): - old_public_cert = old_cert.get('properties', {}).get('publicCertData') - old_ssl_certs.append(old_public_cert) - if not old_response: self.log("Application Gateway instance doesn't exist") if self.state == 'absent': @@ -2429,13 +2338,6 @@ def exec_module(self, **kwargs): self.log("Need to check if Application Gateway instance has to be deleted or may be updated") self.to_do = Actions.Update - self.results['compare'] = [] - if self.identity: - update_identity, identity = self.update_identities(old_response.get('identity', {})) - else: - update_identity = False - identity = None - if (self.to_do == Actions.Update): if (old_response['operational_state'] == 'Stopped' and self.gateway_state == 'started'): self.to_do = Actions.Start @@ -2444,8 +2346,27 @@ def exec_module(self, **kwargs): elif ((old_response['operational_state'] == 'Stopped' and self.gateway_state == 'stopped') or (old_response['operational_state'] == 'Running' and self.gateway_state == 'started')): self.to_do = Actions.NoAction - elif (not self.idempotency_check(old_response, self.parameters) or - update_identity is True): + elif (self.parameters['location'] != old_response['location'] or + self.parameters['enable_http2'] != old_response.get('enable_http2', False) or + self.parameters['sku']['name'] != old_response['sku']['name'] or + self.parameters['sku']['tier'] != old_response['sku']['tier'] or + self.parameters['sku'].get('capacity', None) != old_response['sku'].get('capacity', None) or + not compare_arrays(old_response, self.parameters, 'authentication_certificates') or + not compare_dicts(old_response, self.parameters, 'ssl_policy') or + not compare_arrays(old_response, self.parameters, 'gateway_ip_configurations') or + not compare_arrays(old_response, self.parameters, 'redirect_configurations') or + not compare_arrays(old_response, self.parameters, 'rewrite_rule_sets') or + not compare_arrays(old_response, self.parameters, 'frontend_ip_configurations') or + not compare_arrays(old_response, self.parameters, 'frontend_ports') or + not compare_arrays(old_response, self.parameters, 'backend_address_pools') or + not compare_arrays(old_response, self.parameters, 'probes') or + not compare_arrays(old_response, self.parameters, 'backend_http_settings_collection') or + not compare_arrays(old_response, self.parameters, 'request_routing_rules') or + not compare_arrays(old_response, self.parameters, 'http_listeners') or + not compare_arrays(old_response, self.parameters, 'url_path_maps') or + not compare_arrays(old_response, self.parameters, 'trusted_root_certificates') or + not compare_dicts(old_response, self.parameters, 'autoscale_configuration') or + not compare_dicts(old_response, self.parameters, 'web_application_firewall_configuration')): self.to_do = Actions.Update else: self.to_do = Actions.NoAction @@ -2455,8 +2376,6 @@ def exec_module(self, **kwargs): self.to_do = Actions.Update self.parameters["tags"] = new_tags - self.parameters.update({"identity": identity}) - if (self.to_do == Actions.Create) or (self.to_do == Actions.Update): self.log("Need to Create / Update the Application Gateway instance") @@ -2467,18 +2386,10 @@ def exec_module(self, **kwargs): response = self.create_update_applicationgateway() - properties = self.get_resource() or {} - new_ssl_certs = [] - if properties: - for new_cert in properties.get('properties', {}).get('sslCertificates', []): - new_public_cert = new_cert.get('properties', {}).get('publicCertData') - new_ssl_certs.append(new_public_cert) - if not old_response: self.results['changed'] = True else: - self.results['changed'] = not compare_dicts(old_response, response) or \ - old_ssl_certs.__ne__(new_ssl_certs) + self.results['changed'] = old_response.__ne__(response) self.log("Creation / Update done") elif (self.to_do == Actions.Start) or (self.to_do == Actions.Stop): self.log("Need to Start / Stop the Application Gateway instance") @@ -2608,37 +2519,6 @@ def format_response(self, appgw_dict): } return d - def get_resource(self): - - url = '/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Network/' \ - 'applicationGateways/{2}'.format(self.subscription_id, self.resource_group, self.name) - - query_parameters = {} - query_parameters['api-version'] = '2022-05-01' - header_parameters = {} - header_parameters['Content-Type'] = 'application/json; charset=utf-8' - status_code = [200, 201, 202] - - found = False - try: - response = self.mgmt_client.query(url, - 'GET', - query_parameters, - header_parameters, - None, - status_code, - 600, - 30) - response = json.loads(response.body()) - found = True - self.log("Response : {0}".format(response)) - except Exception as e: - self.log('Did not find the AppGateway instance.') - if found is True: - return response - - return False - def public_ip_id(subscription_id, resource_group_name, name): """Generate the id for a frontend ip configuration""" @@ -2800,13 +2680,16 @@ def trusted_root_certificate_id(subscription_id, resource_group_name, appgateway ) -def compare_dicts(old_response, new_response): +def compare_dicts(old_params, new_params, param_name): """Compare two dictionaries using recursive_diff method and assuming that null values coming from yaml input are acting like absent values""" + oldd = old_params.get(param_name, {}) + newd = new_params.get(param_name, {}) - oldd = array_to_dict([old_response]) - newd = array_to_dict([new_response]) - diffs = recursive_diff(oldd, newd, skip_keys=['etag']) + if oldd == {} and newd == {}: + return True + + diffs = recursive_diff(oldd, newd) if diffs is None: return True else: @@ -2814,6 +2697,21 @@ def compare_dicts(old_response, new_response): return all(value is None or not value for value in actual_diffs.values()) +def compare_arrays(old_params, new_params, param_name): + '''Compare two arrays, including any nested properties on elements.''' + old = old_params.get(param_name, []) + new = new_params.get(param_name, []) + + if old == [] and new == []: + return True + + oldd = array_to_dict(old) + newd = array_to_dict(new) + + newd = dict_merge(oldd, newd) + return newd == oldd + + def array_to_dict(array): '''Converts list object to dictionary object, including any nested properties on elements.''' new = {} @@ -2826,41 +2724,6 @@ def array_to_dict(array): return new -def recursive_diff(dict1, dict2, skip_keys=None): - """Recursively diff two dictionaries - - Raises ``TypeError`` for incorrect argument type. - - :arg dict1: Dictionary to compare against. - :arg dict2: Dictionary to compare with ``dict1``. - :arg skip_keys: Array of keys to ignore in compare. - :return: Tuple of dictionaries of differences or ``None`` if there are no differences. - """ - - skip_keys = skip_keys or [] - - if not all((isinstance(item, MutableMapping) for item in (dict1, dict2))): - raise TypeError("Unable to diff 'dict1' %s and 'dict2' %s. " - "Both must be a dictionary." % (type(dict1), type(dict2))) - - left = dict((k, v) for (k, v) in dict1.items() if k not in dict2 and k not in skip_keys) - right = dict((k, v) for (k, v) in dict2.items() if k not in dict1 and k not in skip_keys) - for k in (set(dict1.keys()) & set(dict2.keys())): - if k in skip_keys: - continue - if isinstance(dict1[k], dict) and isinstance(dict2[k], dict): - result = recursive_diff(dict1[k], dict2[k], skip_keys=skip_keys) - if result: - left[k] = result[0] - right[k] = result[1] - elif dict1[k] != dict2[k]: - left[k] = dict1[k] - right[k] = dict2[k] - if left or right: - return left, right - return None - - def main(): """Main execution""" AzureRMApplicationGateways() diff --git a/plugins/modules/azure_rm_batchaccount.py b/plugins/modules/azure_rm_batchaccount.py index 40ba2bfe0..b5ff4d923 100644 --- a/plugins/modules/azure_rm_batchaccount.py +++ b/plugins/modules/azure_rm_batchaccount.py @@ -66,26 +66,6 @@ - batch_service - user_subscription type: str - identity: - description: - - Identity for this resource. - type: dict - version_added: '2.5.0' - suboptions: - type: - description: - - Type of the managed identity - choices: - - SystemAssigned - - UserAssigned - - 'None' - default: 'None' - type: str - user_assigned_identity: - description: - - User Assigned Managed Identity associated to this resource - required: false - type: str state: description: - Assert the state of the Batch Account. @@ -137,7 +117,6 @@ from azure.core.polling import LROPoller from azure.mgmt.batch import BatchManagementClient from azure.core.exceptions import ResourceNotFoundError - from azure.mgmt.batch.models import BatchAccountIdentity, UserAssignedIdentities except ImportError: # This is handled in azure_rm_common pass @@ -175,10 +154,6 @@ def __init__(self): type='str', choices=['batch_service', 'user_subscription'] ), - identity=dict( - type="dict", - options=self.managed_identity_single_spec - ), state=dict( type='str', default='present', @@ -194,22 +169,11 @@ def __init__(self): self.mgmt_client = None self.state = None self.to_do = Actions.NoAction - self._managed_identity = None - self.identity = None super(AzureRMBatchAccount, self).__init__(derived_arg_spec=self.module_arg_spec, supports_check_mode=True, supports_tags=True) - @property - def managed_identity(self): - if not self._managed_identity: - self._managed_identity = { - "identity": BatchAccountIdentity, - "user_assigned": UserAssignedIdentities, - } - return self._managed_identity - def exec_module(self, **kwargs): """Main module execution method""" @@ -245,12 +209,6 @@ def exec_module(self, **kwargs): base_url=self._cloud_environment.endpoints.resource_manager) old_response = self.get_batchaccount() - curr_identity = old_response["identity"] if old_response else None - - update_identity = False - if self.identity: - update_identity, identity_result = self.update_single_managed_identity(curr_identity=curr_identity, new_identity=self.identity) - self.batch_account["identity"] = identity_result.as_dict() if not old_response: self.log("Batch Account instance doesn't exist") @@ -271,7 +229,7 @@ def exec_module(self, **kwargs): if self.batch_account.get('auto_storage_account') is not None: if old_response['auto_storage']['storage_account_id'] != self.batch_account['auto_storage']['storage_account_id']: self.to_do = Actions.Update - if update_tags or update_identity: + if update_tags: self.to_do = Actions.Update if (self.to_do == Actions.Create) or (self.to_do == Actions.Update): @@ -300,8 +258,7 @@ def exec_module(self, **kwargs): if self.state == 'present': self.results.update({ 'id': response.get('id', None), - 'account_endpoint': response.get('account_endpoint', None), - 'new': response + 'account_endpoint': response.get('account_endpoint', None) }) return self.results @@ -322,8 +279,7 @@ def create_update_batchaccount(self): response = self.mgmt_client.batch_account.update(resource_group_name=self.resource_group, account_name=self.name, parameters=dict(tags=self.tags, - auto_storage=self.batch_account.get('auto_storage'), - identity=self.batch_account.get('identity'))) + auto_storage=self.batch_account.get('self.batch_account'))) if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: @@ -382,8 +338,7 @@ def format_item(self, item): 'low_priority_core_quota': item['low_priority_core_quota'], 'pool_quota': item['pool_quota'], 'active_job_and_job_schedule_quota': item['active_job_and_job_schedule_quota'], - 'tags': item.get('tags'), - 'identity': item.get('identity') + 'tags': item.get('tags') } return result diff --git a/plugins/modules/azure_rm_batchaccount_info.py b/plugins/modules/azure_rm_batchaccount_info.py index 6f8dde58b..80930d6db 100644 --- a/plugins/modules/azure_rm_batchaccount_info.py +++ b/plugins/modules/azure_rm_batchaccount_info.py @@ -180,8 +180,7 @@ def format_item(self, item): 'low_priority_core_quota': item['low_priority_core_quota'], 'pool_quota': item['pool_quota'], 'active_job_and_job_schedule_quota': item['active_job_and_job_schedule_quota'], - 'tags': item.get('tags'), - 'identity': item.get('identity') + 'tags': item.get('tags') } return result diff --git a/plugins/modules/azure_rm_capacityreservationgroup.py b/plugins/modules/azure_rm_capacityreservationgroup.py deleted file mode 100644 index d0c61bfea..000000000 --- a/plugins/modules/azure_rm_capacityreservationgroup.py +++ /dev/null @@ -1,273 +0,0 @@ -#!/usr/bin/python -# -# Copyright (c) 2024 xuzhang3 (@xuzhang3), Fred-sun (@Fred-sun) -# -# 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 -__metaclass__ = type - - -DOCUMENTATION = ''' ---- -module: azure_rm_capacityreservationgroup -version_added: "2.4.0" -short_description: Manage Capacity Reservation Group -description: - - Create, update or delete the Capacity Reservation Group. -options: - resource_group: - description: - - Name of resource group. - required: true - type: str - location: - description: - - Valid Azure location. Defaults to location of the resource group. - type: str - name: - description: - - The name of the Capacity Reservation Group. - required: true - type: str - zones: - description: - - Availability Zones to use for this capacity reservation group. - - The zones can be assigned only during creation. - - If not provided, the group supports only regional resources in the region. - - If provided, enforces each capacity reservation in the group to be in one of the zones. - type: list - elements: str - choices: - - '1' - - '2' - - '3' - state: - description: - - State of the Capacity Reservation Group. Use C(present) to create or update and C(absent) to delete. - default: present - type: str - choices: - - absent - - present - -extends_documentation_fragment: - - azure.azcollection.azure - - azure.azcollection.azure_tags - -author: - - xuzhang3 (@xuzhang3) - - Fred-sun (@Fred-sun) - -''' - -EXAMPLES = ''' -- name: Create a Capacity Reservation Group - azure_rm_capacityreservationgroup: - resource_group: myResourceGroup - name: testname01 - zones: - - 1 - - 2 - tags: - key: value - -- name: Delete the Capacity Reservation Group - azure_rm_capacityreservationgroup: - resource_group: myResourceGroup - name: testname01 - state: absent -''' -RETURN = ''' -state: - description: - - Current state of the Capacity Reservation Group. - returned: always - type: complex - contains: - id: - description: - - Resource ID. - returned: always - type: str - sample: "/subscriptions/xxx-xxx/resourceGroups/testRG/providers/Microsoft.Compute/capacityReservationGroups/testname01" - location: - description: - - The Geo-location where the resource lives. - returned: always - type: str - sample: eastus - name: - description: - - Resource name. - returned: always - type: str - sample: testname01 - resource_group: - description: - - Name of resource group. - type: str - returned: always - sample: myResourceGroup - tags: - description: - - Resource tags. - returned: always - type: dict - sample: { 'key': 'value' } - zones: - description: - - A list of all capacity reservation resource ids that belong to capacity reservation group. - returned: always - type: list - sample: ['1', '2'] -''' - -try: - from azure.core.exceptions import ResourceNotFoundError -except ImportError: - # This is handled in azure_rm_common - pass - -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase - - -class AzureRMCapacityReservationGroup(AzureRMModuleBase): - - def __init__(self): - - self.module_arg_spec = dict( - resource_group=dict(type='str', required=True), - name=dict(type='str', required=True), - state=dict(type='str', default='present', choices=['present', 'absent']), - location=dict(type='str'), - zones=dict(type='list', elements='str', choices=['1', '2', '3']), - ) - - self.resource_group = None - self.name = None - self.state = None - self.location = None - self.zones = None - - self.body = dict() - - self.results = dict( - changed=False, - state=dict() - ) - - super(AzureRMCapacityReservationGroup, self).__init__(self.module_arg_spec, - supports_tags=True, - supports_check_mode=True) - - def exec_module(self, **kwargs): - - for key in list(self.module_arg_spec.keys()) + ['tags']: - setattr(self, key, kwargs[key]) - for key in ['tags', 'zones']: - self.body[key] = kwargs[key] - - old_response = self.get_by_name() - - changed = False - results = None - - if old_response is not None: - if self.state == 'present': - update_tags, self.body['tags'] = self.update_tags(old_response['tags']) - if self.location is not None and self.location.lower() != old_response.get('location').lower(): - self.fail('The parameters location not support to udpate') - elif self.body.get('zones') is not None and not all(key in old_response['zones'] for key in self.body[key]): - self.fail('The parameters zones not support to udpate') - elif update_tags: - changed = True - if not self.check_mode: - results = self.update_capacity_reservation_groups(dict(tags=self.body['tags'])) - else: - results = old_response - else: - changed = True - if not self.check_mode: - results = self.delete_capacity_reservation_groups() - else: - resource_group = self.get_resource_group(self.resource_group) - if self.location is None: - # Set default location - self.body['location'] = resource_group.location - - if self.state == 'present': - changed = True - if not self.check_mode: - results = self.create_capacity_reservation_groups(self.body) - else: - changed = False - self.log("The Capacity Reservation Group is not exists") - - self.results['changed'] = changed - self.results['state'] = results - - return self.results - - def get_by_name(self): - response = None - try: - response = self.compute_client.capacity_reservation_groups.get(self.resource_group, self.name) - - except ResourceNotFoundError as exec: - self.log("Failed to get ssh public keys, Exception as {0}".format(exec)) - - return self.to_dict(response) - - def create_capacity_reservation_groups(self, body): - response = None - try: - response = self.to_dict(self.compute_client.capacity_reservation_groups.create_or_update(self.resource_group, self.name, body)) - except Exception as exc: - self.fail("Error creating Capacity Reservation Group {0} - {1}".format(self.name, str(exc))) - - return self.to_dict(response) - - def update_capacity_reservation_groups(self, body): - response = None - try: - response = self.compute_client.capacity_reservation_groups.update(self.resource_group, self.name, body) - except Exception as exc: - self.fail("Error updating Capacity Reservation Group {0} - {1}".format(self.name, str(exc))) - return self.to_dict(response) - - def delete_capacity_reservation_groups(self): - try: - self.compute_client.capacity_reservation_groups.delete(self.resource_group, self.name) - except Exception as exc: - if self.get_by_name() is not None: - self.fail("Error deleting Capacity Reservation Group {0} - {1}".format(self.name, str(exc))) - - def to_dict(self, body): - if body is None: - results = None - elif isinstance(body, dict): - results = dict( - resource_group=self.resource_group, - id=body.get('id'), - name=body.get('name'), - location=body.get('location'), - zones=body.get('zones'), - tags=body.get('tags')) - else: - results = dict( - resource_group=self.resource_group, - id=body.id, - name=body.name, - location=body.location, - zones=body.zones, - tags=body.tags) - return results - - -def main(): - AzureRMCapacityReservationGroup() - - -if __name__ == '__main__': - main() diff --git a/plugins/modules/azure_rm_capacityreservationgroup_info.py b/plugins/modules/azure_rm_capacityreservationgroup_info.py deleted file mode 100644 index aa5502a50..000000000 --- a/plugins/modules/azure_rm_capacityreservationgroup_info.py +++ /dev/null @@ -1,208 +0,0 @@ -#!/usr/bin/python -# -# Copyright (c) 2024 xuzhang3 (@xuzhang3), Fred-sun (@Fred-sun) -# -# 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 -__metaclass__ = type - - -DOCUMENTATION = ''' ---- -module: azure_rm_capacityreservationgroup_info - -version_added: "2.4.0" - -short_description: Get or list the capacity reservation group - -description: - - Get or list the capacity reservation group. - -options: - resource_group: - description: - - Name of the resource group. - type: str - name: - description: - - Name of the capacity reservation group. - type: str - tags: - description: - - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. - type: list - elements: str - -extends_documentation_fragment: - - azure.azcollection.azure - -author: - - xuzhang3 (@xuzhang3) - - Fred-sun (@Fred-sun) - -''' - -EXAMPLES = ''' -- name: Get facts of the capacity reservation group by name - azure_rm_capacityreservationgroup_info: - resource_group: myResourceGroup - name: mycapacityreservationgroup - -- name: List facts of the capacity reservation group by resource group - azure_rm_capacityreservationgroup_info: - resource_group: myResourceGroup - -- name: List facts of the capacity reservation group by subscription and filter by tags - azure_rm_capacityreservationgroup_info: - tags: - - testing - - foo:bar -''' - -RETURN = ''' -capacity_reservation_group: - description: - - Current state of the Capacity Reservation Group. - returned: always - type: complex - contains: - id: - description: - - Resource ID. - returned: always - type: str - sample: "/subscriptions/xxx-xxx/resourceGroups/testRG/providers/Microsoft.Compute/capacityReservationGroups/testname01" - location: - description: - - The Geo-location where the resource lives. - returned: always - type: str - sample: eastus - name: - description: - - Resource name. - returned: always - type: str - sample: testname01 - resource_group: - description: - - Name of resource group. - type: str - returned: always - sample: myResourceGroup - tags: - description: - - Resource tags. - returned: always - type: dict - sample: { 'key': 'value' } - zones: - description: - - A list of all capacity reservation resource ids that belong to capacity reservation group. - returned: always - type: list - sample: ['1', '2'] - type: - description: - - The resource type. - type: str - returned: always - sample: "Microsoft.Compute/capacityReservationGroups/capacityReservations" -''' - -try: - from azure.core.exceptions import HttpResponseError -except Exception: - # This is handled in azure_rm_common - pass - -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase - - -class AzureRMCapacityReservationGroupInfo(AzureRMModuleBase): - - def __init__(self): - - self.module_arg_spec = dict( - resource_group=dict(type='str'), - name=dict(type='str'), - tags=dict(type='list', elements='str') - ) - - self.results = dict( - changed=False, - capacity_reservation_groups=[] - ) - - self.resource_group = None - self.name = None - self.tags = None - - super(AzureRMCapacityReservationGroupInfo, self).__init__(self.module_arg_spec, - supports_check_mode=True, - supports_tags=False, - facts_module=True) - - def exec_module(self, **kwargs): - for key in self.module_arg_spec: - setattr(self, key, kwargs[key]) - - if self.name and self.resource_group: - response = [self.get_by_name()] - elif self.resource_group: - response = self.list_by_resourcegroup() - else: - response = self.list_all() - - for item in response: - if item is not None and self.has_tags(item.tags, self.tags): - self.results['capacity_reservation_groups'].append(self.to_dict(item)) - - return self.results - - def get_by_name(self): - response = None - try: - response = self.compute_client.capacity_reservation_groups.get(self.resource_group, self.name) - - except HttpResponseError as exec: - self.log("Failed to retrieves information about a capacity reservation group, Exception as {0}".format(exec)) - - return response - - def list_by_resourcegroup(self): - response = None - try: - response = self.compute_client.capacity_reservation_groups.list_by_resource_group(self.resource_group) - except HttpResponseError as exec: - self.log("Faild to list ssh public keys by resource group, exception as {0}".format(exec)) - return response - - def list_all(self): - response = None - try: - response = self.compute_client.capacity_reservation_groups.list_by_subscription() - except HttpResponseError as exc: - self.fail("Failed to list all items - {0}".format(str(exc))) - - return response - - def to_dict(self, body): - return dict( - id=body.id, - resource_group=self.resource_group, - name=body.name, - location=body.location, - tags=body.tags, - type=body.type, - zones=body.zones, - ) - - -def main(): - AzureRMCapacityReservationGroupInfo() - - -if __name__ == '__main__': - main() diff --git a/plugins/modules/azure_rm_cdnprofile.py b/plugins/modules/azure_rm_cdnprofile.py index c269368d1..ebac6f22f 100644 --- a/plugins/modules/azure_rm_cdnprofile.py +++ b/plugins/modules/azure_rm_cdnprofile.py @@ -42,8 +42,6 @@ - standard_akamai - standard_chinacdn - standard_microsoft - - standard_azurefrontdoor - - premium_azurefrontdoor state: description: - Assert the state of the CDN profile. Use C(present) to create or update a CDN profile and C(absent) to delete it. @@ -131,11 +129,7 @@ def __init__(self): ), sku=dict( type='str', - choices=[ - 'standard_verizon', 'premium_verizon', 'custom_verizon', 'standard_akamai', - 'standard_chinacdn', 'standard_microsoft', - 'standard_azurefrontdoor', 'premium_azurefrontdoor' - ] + choices=['standard_verizon', 'premium_verizon', 'custom_verizon', 'standard_akamai', 'standard_chinacdn', 'standard_microsoft'] ) ) diff --git a/plugins/modules/azure_rm_containerinstance.py b/plugins/modules/azure_rm_containerinstance.py index 489552dd8..05df1ee8b 100644 --- a/plugins/modules/azure_rm_containerinstance.py +++ b/plugins/modules/azure_rm_containerinstance.py @@ -80,11 +80,6 @@ description: - The password to log in container image registry server. type: str - acr_identity: - description: - - The Identity to use for access to the registry server. - type: str - version_added: '2.5.0' containers: description: - List of containers. @@ -239,36 +234,6 @@ description: - Commit hash for the specified revision type: str - identity: - description: - - Identity for the Server. - type: dict - version_added: '2.5.0' - suboptions: - type: - description: - - Type of the managed identity - required: false - choices: - - SystemAssigned - - SystemAssigned, UserAssigned - - UserAssigned - default: None - type: str - user_assigned_identities: - description: - - User Assigned Managed Identities and its options - required: false - type: dict - default: {} - suboptions: - id: - description: - - List of the user assigned identities IDs associated to the VM - required: false - type: list - elements: str - default: [] force_update: description: - Force update of existing container instance. Any update will result in deletion and recreation of existing containers. @@ -456,15 +421,12 @@ } ''' -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from ansible.module_utils.common.dict_transformations import _snake_to_camel try: from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from azure.mgmt.containerinstance.models import ( - ContainerGroupIdentity, - ) except ImportError: # This is handled in azure_rm_common pass @@ -558,31 +520,7 @@ def create_container_dict_from_obj(container): ) -user_assigned_identities_spec = dict( - id=dict( - type='list', - default=[], - elements='str' - ), -) - -managed_identity_spec = dict( - type=dict( - type='str', - choices=['SystemAssigned', - 'UserAssigned', - 'SystemAssigned, UserAssigned'], - default='None' - ), - user_assigned_identities=dict( - type='dict', - options=user_assigned_identities_spec, - default={} - ), -) - - -class AzureRMContainerInstance(AzureRMModuleBaseExt): +class AzureRMContainerInstance(AzureRMModuleBase): """Configuration class for an Azure RM container instance resource""" def __init__(self): @@ -634,10 +572,6 @@ def __init__(self): default=None, no_log=True ), - acr_identity=dict( - type='str', - default=None, - ), containers=dict( type='list', elements='dict', @@ -660,10 +594,6 @@ def __init__(self): type='list', elements='str', ), - identity=dict( - type='dict', - options=managed_identity_spec - ), ) self.resource_group = None @@ -675,13 +605,11 @@ def __init__(self): self.containers = None self.restart_policy = None self.subnet_ids = None - self.identity = None self.tags = None self.results = dict(changed=False, state=dict()) self.cgmodels = None - self._managed_identity = None required_if = [ ('state', 'present', ['containers']), ('ip_address', 'private', ['subnet_ids']) @@ -692,14 +620,6 @@ def __init__(self): supports_tags=True, required_if=required_if) - @property - def managed_identity(self): - if not self._managed_identity: - self._managed_identity = {"identity": ContainerGroupIdentity, - "user_assigned": dict - } - return self._managed_identity - def exec_module(self, **kwargs): """Main module execution method""" @@ -720,10 +640,6 @@ def exec_module(self, **kwargs): response = self.get_containerinstance() - # Format identities - if self.identity: - update_identity, self.identity = self.update_identities({}) - if not response: self.log("Container Group doesn't exist") @@ -801,8 +717,7 @@ def create_update_containerinstance(self): if self.registry_login_server is not None: registry_credentials = [self.cgmodels.ImageRegistryCredential(server=self.registry_login_server, username=self.registry_username, - password=self.registry_password, - identity=self.acr_identity)] + password=self.registry_password)] ip_address = None @@ -861,7 +776,6 @@ def create_update_containerinstance(self): subnet_ids = [self.cgmodels.ContainerGroupSubnetId(id=item) for item in self.subnet_ids] parameters = self.cgmodels.ContainerGroup(location=self.location, - identity=self.identity, containers=containers, image_registry_credentials=registry_credentials, restart_policy=_snake_to_camel(self.restart_policy, True) if self.restart_policy else None, diff --git a/plugins/modules/azure_rm_containerinstance_info.py b/plugins/modules/azure_rm_containerinstance_info.py index c3c7a078a..9ef9b254c 100644 --- a/plugins/modules/azure_rm_containerinstance_info.py +++ b/plugins/modules/azure_rm_containerinstance_info.py @@ -196,30 +196,6 @@ "name": "myvolume1" } ] - identity: - description: - - Identity for the Server. - type: complex - returned: when available - contains: - type: - description: - - Type of the managed identity - returned: always - sample: UserAssigned - type: str - user_assigned_identities: - description: - - User Assigned Managed Identities and its options - returned: always - type: complex - contains: - id: - description: - - Dict of the user assigned identities IDs associated to the Resource - returned: always - type: dict - elements: dict tags: description: Tags assigned to the resource. Dictionary of string:string pairs. type: dict @@ -370,8 +346,7 @@ def format_item(self, item): 'restart_policy': _camel_to_snake(d.get('restart_policy')) if d.get('restart_policy') else None, 'tags': d.get('tags', None), 'subnet_ids': d.get('subnet_ids', None), - 'volumes': d['volumes'] if 'volumes' in d else [], - 'identity': d.get('identity', None) + 'volumes': d['volumes'] if 'volumes' in d else [] } return d diff --git a/plugins/modules/azure_rm_containerregistry.py b/plugins/modules/azure_rm_containerregistry.py index c2d8b14d5..ff94c537c 100644 --- a/plugins/modules/azure_rm_containerregistry.py +++ b/plugins/modules/azure_rm_containerregistry.py @@ -52,41 +52,6 @@ - Basic - Standard - Premium - identity: - description: - - Identity for the Container Registry. - type: dict - version_added: '2.4.0' - suboptions: - type: - description: - - Type of the managed identity - choices: - - SystemAssigned - - UserAssigned - - None - default: None - type: str - user_assigned_identities: - description: - - User Assigned Managed Identities and its options - required: false - type: dict - default: {} - suboptions: - id: - description: - - List of the user assigned identities IDs associated to the Container Registry - required: false - type: list - elements: str - default: [] - append: - description: - - If the list of identities has to be appended to current identities (true) or if it has to replace current identities (false) - required: false - type: bool - default: True extends_documentation_fragment: - azure.azcollection.azure @@ -183,7 +148,7 @@ type: dict ''' -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: from azure.core.exceptions import ResourceNotFoundError @@ -192,43 +157,12 @@ RegistryUpdateParameters, Sku, RegistryNameCheckRequest, - IdentityProperties, - UserIdentityProperties, ) except ImportError as exc: # This is handled in azure_rm_common pass -user_assigned_identities_spec = dict( - id=dict( - type='list', - default=[], - elements='str' - ), - append=dict( - type='bool', - default=True - ) -) - - -managed_identity_spec = dict( - type=dict( - type='str', - choices=['SystemAssigned', - 'UserAssigned', - 'None'], - default='None' - ), - user_assigned_identities=dict( - type='dict', - options=user_assigned_identities_spec, - default={} - ), -) - - def create_containerregistry_dict(registry, credentials): ''' Helper method to deserialize a ContainerRegistry to a dict @@ -245,7 +179,6 @@ def create_containerregistry_dict(registry, credentials): provisioning_state=registry.provisioning_state if registry is not None else "", login_server=registry.login_server if registry is not None else "", credentials=dict(), - identity=registry.identity.as_dict() if registry is not None and registry.identity else None, tags=registry.tags if registry is not None else "" ) if credentials: @@ -261,7 +194,7 @@ class Actions: NoAction, Create, Update = range(3) -class AzureRMContainerRegistry(AzureRMModuleBaseExt): +class AzureRMContainerRegistry(AzureRMModuleBase): """Configuration class for an Azure RM container registry resource""" def __init__(self): @@ -286,10 +219,6 @@ def __init__(self): type='bool', default=False ), - identity=dict( - type='dict', - options=managed_identity_spec - ), sku=dict( type='str', default='Standard', @@ -303,9 +232,6 @@ def __init__(self): self.state = None self.sku = None self.tags = None - self.identity = None - - self._managed_identity = None self.results = dict(changed=False, state=dict()) @@ -314,14 +240,6 @@ def __init__(self): supports_check_mode=True, supports_tags=True) - @property - def managed_identity(self): - if not self._managed_identity: - self._managed_identity = {"identity": IdentityProperties, - "user_assigned": UserIdentityProperties - } - return self._managed_identity - def exec_module(self, **kwargs): """Main module execution method""" for key in list(self.module_arg_spec.keys()) + ['tags']: @@ -339,22 +257,16 @@ def exec_module(self, **kwargs): if self.state == 'present': if not response: - if self.identity: - update_identity, self.identity = self.update_identities({}) to_do = Actions.Create else: self.log('Results : {0}'.format(response)) self.results.update(response) if response['provisioning_state'] == "Succeeded": - if self.identity: - update_identity, self.identity = self.update_identities(response.get('identity', None)) to_do = Actions.NoAction if (self.location is not None) and self.location != response['location']: to_do = Actions.Update elif (self.sku is not None) and self.sku != response['sku']: to_do = Actions.Update - elif (self.identity is not None) and update_identity: - to_do = Actions.Update else: to_do = Actions.NoAction @@ -405,8 +317,7 @@ def create_update_containerregistry(self, to_do): name=self.sku ), tags=self.tags, - admin_user_enabled=self.admin_user_enabled, - identity=self.identity + admin_user_enabled=self.admin_user_enabled ) ) else: @@ -422,8 +333,7 @@ def create_update_containerregistry(self, to_do): name=self.sku ), tags=self.tags, - admin_user_enabled=self.admin_user_enabled, - identity=self.identity + admin_user_enabled=self.admin_user_enabled ) ) else: diff --git a/plugins/modules/azure_rm_containerregistry_info.py b/plugins/modules/azure_rm_containerregistry_info.py index a41bf64ad..8be247d37 100644 --- a/plugins/modules/azure_rm_containerregistry_info.py +++ b/plugins/modules/azure_rm_containerregistry_info.py @@ -133,30 +133,6 @@ returned: when registry exists and C(admin_user_enabled) is set type: str sample: pass2value - identity: - description: - - Identity for the Server. - type: complex - returned: when available - contains: - type: - description: - - Type of the managed identity - returned: always - sample: UserAssigned - type: str - user_assigned_identities: - description: - - User Assigned Managed Identities and its options - returned: always - type: complex - contains: - id: - description: - - Dict of the user assigned identities IDs associated to the Resource - returned: always - type: dict - elements: dict tags: description: - Tags assigned to the resource. Dictionary of string:string pairs. @@ -288,8 +264,7 @@ def format_item(self, item): 'login_server': d['login_server'], 'id': d['id'], 'tags': d.get('tags', None), - 'credentials': credentials, - 'identity': d.get('identity', None) + 'credentials': credentials } return d diff --git a/plugins/modules/azure_rm_galleryimageversion.py b/plugins/modules/azure_rm_galleryimageversion.py index 4befec9c3..66a4dea6b 100644 --- a/plugins/modules/azure_rm_galleryimageversion.py +++ b/plugins/modules/azure_rm_galleryimageversion.py @@ -63,11 +63,7 @@ suboptions: source: description: - - Reference to os disk snapshot. - - Could be resource ID. - - Could be a dictionary containing I(resource_group) and I(name). - - Could be a dictionary containing I(resource_group), I(storage_account), and I(uri) - if the snapshot is stored as a PageBlob in a storage account container. + - Reference to os disk snapshot. Could be resource ID or dictionary containing I(resource_group) and I(name) type: raw host_caching: description: @@ -307,29 +303,6 @@ name: data_snapshot_vma - lun: 1 source: "/subscriptions/mySub/resourceGroups/myGroup/providers/Microsoft.Compute/snapshots/data_snapshot_vmb" - -- name: Create gallery image by using a os disk snapshot stored in Storage Account container - azure_rm_galleryimageversion: - resource_group: myResourceGroup - gallery_name: myGallery - gallery_image_name: myGalleryImage - name: 3.4.0 - location: East US - publishing_profile: - end_of_life_date: "2020-10-01t00:00:00+00:00" - exclude_from_latest: true - replica_count: 1 - storage_account_type: Standard_LRS - target_regions: - - name: East US - regional_replica_count: 1 - storage_account_type: Standard_LRS - storage_profile: - os_disk: - source: - resource_group: myResourceGroup - storage_account: myStorageAccount - uri: "https://myStorageAccount.blob.core.windows.net/myContainer/myImage.vhd" ''' RETURN = ''' @@ -588,8 +561,8 @@ def exec_module(self, **kwargs): elif isinstance(kwargs[key]['os_disk']['source'], dict): if kwargs[key]['os_disk']['source'].get('id') is not None: self.body['properties']['storageProfile']['osDiskImage']['source']['id'] = kwargs[key]['os_disk']['source'].get('id') - elif kwargs[key]['os_disk']['source'].get('resource_group') is not None and \ - kwargs[key]['os_disk']['source'].get('name') is not None: + if kwargs[key]['os_disk']['source'].get('resource_group') is not None and \ + kwargs[key]['os_disk']['source'].get('name') is not None: resource_group = kwargs[key]['os_disk']['source'].get('resource_group') self.body['properties']['storageProfile']['osDiskImage']['source']['id'] = ('/subscriptions/' + self.subscription_id + @@ -597,19 +570,6 @@ def exec_module(self, **kwargs): resource_group + '/providers/Microsoft.Compute/snapshots/' + kwargs[key]['os_disk']['source'].get('name')) - elif kwargs[key]['os_disk']['source'].get('uri') is not None and \ - kwargs[key]['os_disk']['source'].get('resource_group') is not None and \ - kwargs[key]['os_disk']['source'].get('storage_account') is not None: - resource_group = kwargs[key]['os_disk']['source'].get('resource_group') - storage_account = kwargs[key]['os_disk']['source'].get('storage_account') - self.body['properties']['storageProfile']['osDiskImage']['source']['id'] = ('/subscriptions/' + - self.subscription_id + - '/resourceGroups/' + - resource_group + - '/providers/Microsoft.Storage' + - '/storageAccounts/' + - storage_account) - self.body['properties']['storageProfile']['osDiskImage']['source']['uri'] = kwargs[key]['os_disk']['source'].get('uri') else: self.fail("The os_disk.source parameters config errors") diff --git a/plugins/modules/azure_rm_networkflowlog.py b/plugins/modules/azure_rm_networkflowlog.py deleted file mode 100644 index 4a0cabf06..000000000 --- a/plugins/modules/azure_rm_networkflowlog.py +++ /dev/null @@ -1,477 +0,0 @@ -#!/usr/bin/python -# -# Copyright (c) 2024 xuzhang3 (@xuzhang3), Fred-sun (@Fred-sun) -# -# 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 -__metaclass__ = type - - -DOCUMENTATION = ''' ---- -module: azure_rm_networkflowlog -version_added: "2.5.0" -short_description: Manage the network flow logs -description: - - Create, update or delete the network flow logs. -options: - resource_group: - description: - - Name of resource group. - required: true - type: str - location: - description: - - Valid Azure location. Defaults to location of the resource group. - type: str - name: - description: - - The name of the network flow logs. - required: true - type: str - network_watcher_name: - description: - - The name of the network watcher. - type: str - required: true - target_resource_id: - description: - - ID of network security group to which flow log will be applied. - type: str - storage_id: - description: - - ID of the storage account which is used to store the flow log. - type: str - enabled: - description: - - Flag to enable/disable flow logging. - type: bool - retention_policy: - description: - - Parameters that define the retention policy for flow log. - type: dict - suboptions: - days: - description: - - Number of days to retain flow log records. - type: int - enabled: - description: - - Flag to enable/disable retention. - type: bool - flow_analytics_configuration: - description: - - Parameters that define the configuration of traffic analytics. - type: dict - suboptions: - network_watcher_flow_analytics_configuration: - description: - - Parameters that define the configuration of traffic analytics. - type: dict - suboptions: - enabled: - description: - - Flag to enable/disable traffic analytics. - type: bool - workspace_id: - description: - - The resource guid of the attached workspace. - type: str - workspace_region: - description: - - The location of the attached workspace. - type: str - workspace_resource_id: - description: - - Resource Id of the attached workspace. - type: str - traffic_analytics_interval: - description: - - The interval in minutes which would decide how frequently TA service should do flow analytics. - type: int - choices: - - 10 - - 60 - state: - description: - - State of the Flow Logs. Use C(present) to create or update and C(absent) to delete. - default: present - type: str - choices: - - absent - - present - -extends_documentation_fragment: - - azure.azcollection.azure - - azure.azcollection.azure_tags - -author: - - xuzhang3 (@xuzhang3) - - Fred-sun (@Fred-sun) - -''' - -EXAMPLES = ''' -- name: Create network flow log - azure_rm_networkflowlog: - resource_group: NetworkWatcherRG - network_watcher_name: NetworkWatcher_eastus - name: xz3mlwvnet-xz3mlwaiserv-flowlog02 - enabled: false - flow_analytics_configuration: - network_watcher_flow_analytics_configuration: - enabled: false - traffic_analytics_interval: 60 - workspace_id: 7c16a8dd-b983-4f75-b78b-a804c169306c - workspace_region: eastus - workspace_resource_id: "/subscriptions/xxx-xxx/resourceGroups/DefaultRG-EUS/providers/Microsoft.OperationalInsights/workspaces/DeWorkspace-0-EUS" - retention_policy: - days: 2 - enabled: true - storage_id: "/subscriptions/xxx-xxx/resourceGroups/AutoTagFunctionAppRG/providers/Microsoft.Storage/storageAccounts/autotagfunctionappr9a08" - target_resource_id: "/subscriptions/xxx-xxx/resourceGroups/xz3mlwaiserv/providers/Microsoft.Network/virtualNetworks/xz3mlwvnet" - tags: - key2: value2 - key5: value5 - -- name: Delete a Flow Logs - azure_rm_networkflowlog: - resource_group: myResourceGroup - network_watcher_name: testwatcher - name: myNetflowlog - state: absent -''' -RETURN = ''' -state: - description: - - The facts of the network flow logs. - returned: always - type: complex - contains: - resource_group: - description: - - The resource group. - type: str - returned: always - sample: NetworkWatcherRG - id: - description: - - Resource ID. - returned: always - type: str - sample: /subscriptions/xxx-xxx/resourceGroups/NetWatcherRG/providers/Microsoft.Network/networkWatchers/NetWatcher_eastus/flowLogs/xz-flowlog" - location: - description: - - Resource location. - returned: always - type: str - sample: eastus - name: - description: - - Resource name. - returned: always - type: str - sample: xz-flowlog - network_watcher_name: - description: - - The name of the network watcher. - type: str - returned: always - sample: NetWatcher_eastus - target_resource_id: - description: - - ID of network security group to which flow log will be applied. - type: str - returned: always - sample: /subscriptions/xxx-xxx/resourceGroups/xz3mlwaiserv/providers/Microsoft.Network/virtualNetworks/xz3mlwvnet" - storage_id: - description: - - ID of the storage account which is used to store the flow log. - type: str - returned: always - sample: "/subscriptions/xxx-xxx/resourceGroups/AutoTagFunctionAppRG/providers/Microsoft.Storage/storageAccounts/autotagfunc01" - enanbled: - description: - - Flag to enable/disable flow logging. - type: str - returned: always - sample: true - retention_policy: - description: - - Parameters that define the retention policy for flow log. - type: complex - returned: always - contains: - day: - description: - - Number of days to retain flow log records. - type: int - returned: always - sample: 0 - enabled: - description: - - Flag to enable/disable retention. - type: bool - returned: always - sample: false - flow_analytics_configuration: - description: - - Parameters that define the configuration of traffic analytics. - type: complex - returned: always - contains: - network_watcher_flow_analytics_configuration: - description: - - Parameters that define the configuration of traffic analytics. - type: complex - returned: always - contains: - enabled: - description: - - Flag to enable/disable traffic analytics. - type: bool - returned: always - sample: true - workspace_id: - description: - - The resource guid of the attached workspace. - type: str - returned: always - sample: 7c16a8dd-b983-4f75-b78b-a804c169306c - workspace_region: - description: - - The location of the attached workspace. - type: str - returned: always - sample: eastus - workspace_resource_id: - description: - - Resource Id of the attached workspace. - type: str - returned: always - sample: /subscriptions/xxx-xxx/resourceGroups/DefaulUS/providers/Microsoft.OperationalInsights/workspaces/DefaultWorkspace-0-EUS" - traffic_analytics_interval: - description: - - The interval in minutes which would decide how frequently TA service should do flow analytics. - type: str - returned: always - sample: 60 - tags: - description: - - Resource tags. - returned: always - type: dict - sample: { 'key1':'value1' } - type: - description: - - Resource type. - returned: always - type: str - sample: "Microsoft.Network/networkWatchers/flowLogs" - provisioning_state: - description: - - The provisioning state of the network flow logs resource. - type: str - returned: always - sample: Succeeded -''' - -try: - from azure.core.exceptions import ResourceNotFoundError -except ImportError: - # This is handled in azure_rm_common - pass - -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt - - -class AzureRMNetworkFlowLog(AzureRMModuleBaseExt): - - def __init__(self): - - self.module_arg_spec = dict( - resource_group=dict(type='str', required=True), - network_watcher_name=dict(type='str', required=True), - name=dict(type='str', required=True), - state=dict(type='str', default='present', choices=['present', 'absent']), - location=dict(type='str'), - target_resource_id=dict(type='str'), - storage_id=dict(type='str'), - enabled=dict(type='bool'), - retention_policy=dict( - type='dict', - options=dict( - days=dict(type='int'), - enabled=dict(type='bool'), - ), - ), - flow_analytics_configuration=dict( - type='dict', - options=dict( - network_watcher_flow_analytics_configuration=dict( - type='dict', - options=dict( - enabled=dict(type='bool'), - workspace_id=dict(type='str'), - workspace_region=dict(type='str'), - workspace_resource_id=dict(type='str'), - traffic_analytics_interval=dict(type='int', choices=[10, 60]) - ) - ) - ) - ), - ) - - self.resource_group = None - self.network_watcher_name = None - self.name = None - self.state = None - self.location = None - self.tags = None - self.body = dict() - - self.results = dict( - changed=False, - state=dict() - ) - - super(AzureRMNetworkFlowLog, self).__init__(self.module_arg_spec, - supports_tags=True, - supports_check_mode=True) - - def exec_module(self, **kwargs): - - for key in list(self.module_arg_spec.keys()) + ['tags']: - if hasattr(self, key): - setattr(self, key, kwargs[key]) - elif kwargs[key] is not None: - self.body[key] = kwargs[key] - - resource_group = self.get_resource_group(self.resource_group) - if self.body.get('location') is None: - # Set default location - self.body['location'] = resource_group.location - self.body['tags'] = self.tags - - changed = False - results = dict() - - old_response = self.get_by_name() - - if old_response is not None: - if self.state == 'present': - if self.body.get('retention_policy') is not None and\ - not self.default_compare({}, self.body.get('retention_policy'), old_response.get('retention_policy'), '', dict(compare=[])): - changed = True - elif (self.body.get('flow_analytics_configuration') is not None and not self.default_compare( - {}, self.body['flow_analytics_configuration'], old_response['flow_analytics_configuration'], '', dict(compare=[]))): - changed = True - - elif self.body.get('enabled') is not None and bool(self.body['enabled']) != bool(old_response.get('enabled')): - changed = True - if changed: - results = self.create_or_update(self.body) - else: - results = old_response - - update_tags, new_tags = self.update_tags(old_response['tags']) - if update_tags: - changed = True - if not self.check_mode: - results = self.update_flowlog_tags(new_tags) - else: - changed = True - if not self.check_mode: - results = self.delete_flowlog() - else: - if self.state == 'present': - changed = True - if not self.check_mode: - results = self.create_or_update(self.body) - else: - changed = False - self.log("The Flow Log is not exists") - - self.results['changed'] = changed - self.results['state'] = results - - return self.results - - def get_by_name(self): - response = None - try: - response = self.network_client.flow_logs.get(self.resource_group, self.network_watcher_name, self.name) - - except ResourceNotFoundError as exec: - self.log("Failed to get network flow log, Exception as {0}".format(exec)) - - return self.to_dict(response) - - def create_or_update(self, body): - response = None - try: - response = self.network_client.flow_logs.begin_create_or_update(self.resource_group, self.network_watcher_name, self.name, body) - response = self.get_poller_result(response) - except Exception as exc: - self.fail("Error creating Flow Log {0} - {1}".format(self.name, str(exc))) - - return self.to_dict(response) - - def update_flowlog_tags(self, tags): - response = None - try: - response = self.network_client.flow_logs.update_tags(self.resource_group, self.network_watcher_name, self.name, dict(tags=tags)) - except Exception as exc: - self.fail("Error updating Flow Logs {0} - {1}".format(self.name, str(exc))) - return self.to_dict(response) - - def delete_flowlog(self): - try: - self.network_client.flow_logs.begin_delete(self.resource_group, self.network_watcher_name, self.name) - except Exception as exc: - self.fail("Error deleting Flow Logs {0} - {1}".format(self.name, str(exc))) - - def to_dict(self, body): - results = dict() - if body is not None: - results = dict( - resource_group=self.resource_group, - network_watcher_name=self.network_watcher_name, - id=body.id, - name=body.name, - location=body.location, - tags=body.tags, - type=body.type, - provisioning_state=body.provisioning_state, - target_resource_id=body.target_resource_id, - storage_id=body.storage_id, - enabled=body.enabled, - retention_policy=dict(), - flow_analytics_configuration=dict() - ) - if body.retention_policy is not None: - results['retention_policy']['days'] = body.retention_policy.days - results['retention_policy']['enabled'] = body.retention_policy.enabled - if body.flow_analytics_configuration is not None: - results['flow_analytics_configuration']['network_watcher_flow_analytics_configuration'] = dict() - if body.flow_analytics_configuration.network_watcher_flow_analytics_configuration is not None: - new_config = body.flow_analytics_configuration.network_watcher_flow_analytics_configuration - results['flow_analytics_configuration']['network_watcher_flow_analytics_configuration']['enabled'] = new_config.enabled - results['flow_analytics_configuration']['network_watcher_flow_analytics_configuration']['workspace_id'] = new_config.workspace_id - results['flow_analytics_configuration']['network_watcher_flow_analytics_configuration']['workspace_region'] = new_config.workspace_region - results['flow_analytics_configuration']['network_watcher_flow_analytics_configuration']['workspace_resource_id'] = \ - new_config.workspace_resource_id - results['flow_analytics_configuration']['network_watcher_flow_analytics_configuration']['traffic_analytics_interval'] = \ - new_config.traffic_analytics_interval - - return results - return None - - -def main(): - AzureRMNetworkFlowLog() - - -if __name__ == '__main__': - main() diff --git a/plugins/modules/azure_rm_networkflowlog_info.py b/plugins/modules/azure_rm_networkflowlog_info.py deleted file mode 100644 index 860a7cfe3..000000000 --- a/plugins/modules/azure_rm_networkflowlog_info.py +++ /dev/null @@ -1,309 +0,0 @@ -#!/usr/bin/python -# -# Copyright (c) 2024 xuzhang3 (@xuzhang3), Fred-sun (@Fred-sun) -# -# 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 -__metaclass__ = type - - -DOCUMENTATION = ''' ---- -module: azure_rm_networkflowlog_info - -version_added: "2.5.0" - -short_description: Get or list the network flow logs - -description: - - Get or list the network flow logs facts. - -options: - resource_group: - description: - - The name of the resource group. - type: str - required: true - network_watcher_name: - description: - - Name of the network watcher. - type: str - required: true - name: - description: - - Name of the network flow logs. - type: str - tags: - description: - - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. - type: list - elements: str - -extends_documentation_fragment: - - azure.azcollection.azure - -author: - - xuzhang3 (@xuzhang3) - - Fred-sun (@Fred-sun) - -''' - -EXAMPLES = ''' -- name: Get the network watcher facts - azure_rm_networkflowlog_info: - resource_group: myResourceGroup - network_watcher_name: mywatcher01 - name: flowlogname - -- name: list the network flow logs and filter by tags - azure_rm_networkflowlog_info: - resource_group: myResourceGroup - network_watcher_name: mywatcher01 - tags: - - key1 -''' - -RETURN = ''' -flow_logs: - description: - - The facts of the network flow logs. - returned: always - type: complex - contains: - resource_group: - description: - - The resource group. - type: str - returned: always - sample: NetworkWatcherRG - id: - description: - - Resource ID. - returned: always - type: str - sample: /subscriptions/xxx-xxx/resourceGroups/NetWatcherRG/providers/Microsoft.Network/networkWatchers/NetWatcher_eastus/flowLogs/xz-flowlog" - location: - description: - - Resource location. - returned: always - type: str - sample: eastus - name: - description: - - Resource name. - returned: always - type: str - sample: xz-flowlog - network_watcher_name: - description: - - The name of the network watcher. - type: str - returned: always - sample: NetWatcher_eastus - target_resource_id: - description: - - ID of network security group to which flow log will be applied. - type: str - returned: always - sample: /subscriptions/xxx-xxx/resourceGroups/xz3mlwaiserv/providers/Microsoft.Network/virtualNetworks/xz3mlwvnet" - storage_id: - description: - - ID of the storage account which is used to store the flow log. - type: str - returned: always - sample: "/subscriptions/xxx-xxx/resourceGroups/AutoTagFunctionAppRG/providers/Microsoft.Storage/storageAccounts/autotagfunc01" - enanbled: - description: - - Flag to enable/disable flow logging. - type: str - returned: always - sample: true - retention_policy: - description: - - Parameters that define the retention policy for flow log. - type: complex - returned: always - contains: - day: - description: - - Number of days to retain flow log records. - type: int - returned: always - sample: 0 - enabled: - description: - - Flag to enable/disable retention. - type: bool - returned: always - sample: false - flow_analytics_configuration: - description: - - Parameters that define the configuration of traffic analytics. - type: complex - returned: always - contains: - network_watcher_flow_analytics_configuration: - description: - - Parameters that define the configuration of traffic analytics. - type: complex - returned: always - contains: - enabled: - description: - - Flag to enable/disable traffic analytics. - type: bool - returned: always - sample: true - workspace_id: - description: - - The resource guid of the attached workspace. - type: str - returned: always - sample: 7c16a8dd-b983-4f75-b78b-a804c169306c - workspace_region: - description: - - The location of the attached workspace. - type: str - returned: always - sample: eastus - workspace_resource_id: - description: - - Resource Id of the attached workspace. - type: str - returned: always - sample: /subscriptions/xxx-xxx/resourceGroups/DefaulUS/providers/Microsoft.OperationalInsights/workspaces/DefaultWorkspace-0-EUS" - traffic_analytics_interval: - description: - - The interval in minutes which would decide how frequently TA service should do flow analytics. - type: str - returned: always - sample: 60 - tags: - description: - - Resource tags. - returned: always - type: dict - sample: { 'key1':'value1' } - type: - description: - - Resource type. - returned: always - type: str - sample: "Microsoft.Network/networkWatchers/flowLogs" - provisioning_state: - description: - - The provisioning state of the network flow logs resource. - type: str - returned: always - sample: Succeeded -''' - -try: - from azure.core.exceptions import ResourceNotFoundError -except Exception: - # This is handled in azure_rm_common - pass - -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase - - -class AzureRMNetworkFlowLogInfo(AzureRMModuleBase): - - def __init__(self): - - self.module_arg_spec = dict( - resource_group=dict(type='str', required=True), - network_watcher_name=dict(type='str', required=True), - name=dict(type='str'), - tags=dict(type='list', elements='str') - ) - - self.results = dict( - changed=False, - flow_logs=[] - ) - - self.resource_group = None - self.network_watcher_name = None - self.name = None - self.tags = None - - super(AzureRMNetworkFlowLogInfo, self).__init__(self.module_arg_spec, - supports_check_mode=True, - supports_tags=False, - facts_module=True) - - def exec_module(self, **kwargs): - for key in self.module_arg_spec: - setattr(self, key, kwargs[key]) - - if self.name: - response = [self.get_by_name()] - else: - response = self.list_by_network_watcher() - - self.results['flow_logs'] = [self.to_dict(item) for item in response if response is not None] - - return self.results - - def get_by_name(self): - response = None - try: - response = self.network_client.flow_logs.get(self.resource_group, self.network_watcher_name, self.name) - - except ResourceNotFoundError as exec: - self.log("Failed to get network flow logs, Exception as {0}".format(exec)) - - return response - - def list_by_network_watcher(self): - response = [] - try: - response = self.network_client.flow_logs.list(self.resource_group, self.network_watcher_name) - except Exception as exec: - self.log("Faild to list network flow logs by network watcher, exception as {0}".format(exec)) - return response - - def to_dict(self, body): - results = dict() - if body is not None and self.has_tags(body.tags, self.tags): - results = dict( - resource_group=self.resource_group, - network_watcher_name=self.network_watcher_name, - id=body.id, - name=body.name, - location=body.location, - tags=body.tags, - type=body.type, - provisioning_state=body.provisioning_state, - target_resource_id=body.target_resource_id, - storage_id=body.storage_id, - enabled=body.enabled, - retention_policy=dict(), - flow_analytics_configuration=dict() - ) - if body.retention_policy is not None: - results['retention_policy']['days'] = body.retention_policy.days - results['retention_policy']['enabled'] = body.retention_policy.enabled - if body.flow_analytics_configuration is not None: - results['flow_analytics_configuration']['network_watcher_flow_analytics_configuration'] = dict() - if body.flow_analytics_configuration.network_watcher_flow_analytics_configuration is not None: - new_config = body.flow_analytics_configuration.network_watcher_flow_analytics_configuration - results['flow_analytics_configuration']['network_watcher_flow_analytics_configuration']['enabled'] = new_config.enabled - results['flow_analytics_configuration']['network_watcher_flow_analytics_configuration']['workspace_id'] = new_config.workspace_id - results['flow_analytics_configuration']['network_watcher_flow_analytics_configuration']['workspace_region'] = new_config.workspace_region - results['flow_analytics_configuration']['network_watcher_flow_analytics_configuration']['workspace_resource_id'] = \ - new_config.workspace_resource_id - results['flow_analytics_configuration']['network_watcher_flow_analytics_configuration']['traffic_analytics_interval'] = \ - new_config.traffic_analytics_interval - - return results - - -def main(): - AzureRMNetworkFlowLogInfo() - - -if __name__ == '__main__': - main() diff --git a/plugins/modules/azure_rm_networkwatcher.py b/plugins/modules/azure_rm_networkwatcher.py deleted file mode 100644 index 3a9bed0b0..000000000 --- a/plugins/modules/azure_rm_networkwatcher.py +++ /dev/null @@ -1,249 +0,0 @@ -#!/usr/bin/python -# -# Copyright (c) 2024 xuzhang3 (@xuzhang3), Fred-sun (@Fred-sun) -# -# 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 -__metaclass__ = type - - -DOCUMENTATION = ''' ---- -module: azure_rm_networkwatcher -version_added: "2.5.0" -short_description: Manage the network watcher -description: - - Create, update or delete the network watcher. -options: - resource_group: - description: - - Name of resource group. - required: true - type: str - location: - description: - - Valid Azure location. Defaults to location of the resource group. - type: str - name: - description: - - The name of the network watcher. - required: true - type: str - state: - description: - - State of the Network Watcher. Use C(present) to create or update and C(absent) to delete. - default: present - type: str - choices: - - absent - - present - -extends_documentation_fragment: - - azure.azcollection.azure - - azure.azcollection.azure_tags - -author: - - xuzhang3 (@xuzhang3) - - Fred-sun (@Fred-sun) - -''' - -EXAMPLES = ''' -- name: Create a Network Watcher - azure_rm_networkwatcher: - resource_group: myResourceGroup - name: myNetworkWatcher - location: eastus - tags: - testing: testing - delete: on-exit - -- name: Delete a Network Watcher - azure_rm_networkwatcher: - resource_group: myResourceGroup - name: myNetworkWatcher - state: absent -''' -RETURN = ''' -state: - description: - - The facts of the network watcher. - returned: always - type: complex - contains: - resource_group: - description: - - The resource group. - type: str - returned: always - sample: NetworkWatcherRG - id: - description: - - Resource ID. - returned: always - type: str - sample: "/subscriptions/xxx-xxx/resourceGroups/NetworkWatcherRG/providers/Microsoft.Network/networkWatchers/netwatcher_eastus" - location: - description: - - Resource location. - returned: always - type: str - sample: eastus - name: - description: - - Resource name. - returned: always - type: str - sample: mynetworkwatcher01 - tags: - description: - - Resource tags. - returned: always - type: dict - sample: { 'key1':'value1' } - type: - description: - - Resource type. - returned: always - type: str - sample: "Microsoft.Network/networkWatchers" - provisioning_state: - description: - - The provisioning state of the network watcher resource. - type: str - returned: always - sample: Succeeded -''' - -try: - from azure.core.exceptions import ResourceNotFoundError -except ImportError: - # This is handled in azure_rm_common - pass - -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase - - -class AzureRMNetworkWatcher(AzureRMModuleBase): - - def __init__(self): - - self.module_arg_spec = dict( - resource_group=dict(type='str', required=True), - name=dict(type='str', required=True), - state=dict(type='str', default='present', choices=['present', 'absent']), - location=dict(type='str'), - ) - - self.resource_group = None - self.name = None - self.state = None - self.location = None - self.tags = None - - self.results = dict( - changed=False, - state=dict() - ) - - super(AzureRMNetworkWatcher, self).__init__(self.module_arg_spec, - supports_tags=True, - supports_check_mode=True) - - def exec_module(self, **kwargs): - - for key in list(self.module_arg_spec.keys()) + ['tags']: - setattr(self, key, kwargs[key]) - - resource_group = self.get_resource_group(self.resource_group) - if not self.location: - # Set default location - self.location = resource_group.location - - changed = False - results = dict() - - old_response = self.get_by_name() - - if old_response is not None: - if self.state == 'present': - update_tags, new_tags = self.update_tags(old_response['tags']) - if update_tags: - changed = True - if not self.check_mode: - results = self.update_watcher_tags(dict(tags=new_tags)) - else: - results = old_response - else: - changed = True - if not self.check_mode: - results = self.delete_network_watcher() - else: - if self.state == 'present': - changed = True - if not self.check_mode: - results = self.create_or_update(dict(tags=self.tags, location=self.location)) - else: - changed = False - self.log("The Network Watcher is not exists") - - self.results['changed'] = changed - self.results['state'] = results - - return self.results - - def get_by_name(self): - response = None - try: - response = self.network_client.network_watchers.get(self.resource_group, self.name) - - except ResourceNotFoundError as exec: - self.log("Failed to get network watcher, Exception as {0}".format(exec)) - - return self.to_dict(response) - - def create_or_update(self, body): - response = None - try: - response = self.to_dict(self.network_client.network_watchers.create_or_update(self.resource_group, self.name, body)) - except Exception as exc: - self.fail("Error creating Network Watcher {0} - {1}".format(self.name, str(exc))) - - return response - - def update_watcher_tags(self, body): - response = None - try: - response = self.network_client.network_watchers.update_tags(self.resource_group, self.name, body) - except Exception as exc: - self.fail("Error updating Network Watcher {0} - {1}".format(self.name, str(exc))) - return self.to_dict(response) - - def delete_network_watcher(self): - try: - self.network_client.network_watchers.begin_delete(self.resource_group, self.name) - except Exception as exc: - self.fail("Error deleting Network Watcher {0} - {1}".format(self.name, str(exc))) - - def to_dict(self, body): - results = None - if body is not None: - results = dict( - resource_group=self.resource_group, - id=body.id, - name=body.name, - location=body.location, - tags=body.tags, - type=body.type, - provisioning_state=body.provisioning_state, - ) - return results - - -def main(): - AzureRMNetworkWatcher() - - -if __name__ == '__main__': - main() diff --git a/plugins/modules/azure_rm_networkwatcher_info.py b/plugins/modules/azure_rm_networkwatcher_info.py deleted file mode 100644 index 4672f5579..000000000 --- a/plugins/modules/azure_rm_networkwatcher_info.py +++ /dev/null @@ -1,211 +0,0 @@ -#!/usr/bin/python -# -# Copyright (c) 2024 xuzhang3 (@xuzhang3), Fred-sun (@Fred-sun) -# -# 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 -__metaclass__ = type - - -DOCUMENTATION = ''' ---- -module: azure_rm_networkwatcher_info - -version_added: "2.5.0" - -short_description: Get or list the network watcher facts - -description: - - Get or list the network watcher facts. - -options: - resource_group: - description: - - The name of the resource group. - type: str - name: - description: - - Name of the network watcher. - type: str - tags: - description: - - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. - type: list - elements: str - -extends_documentation_fragment: - - azure.azcollection.azure - -author: - - xuzhang3 (@xuzhang3) - - Fred-sun (@Fred-sun) - -''' - -EXAMPLES = ''' -- name: Get the network watcher facts - azure_rm_networkwatcher_info: - resource_group: myResourceGroup - name: mywatcher01 - -- name: list the network watcher facts - azure_rm_networkwatcher_info: - resource_group: myResourceGroup - -- name: list the network watcher and filter by tags - azure_rm_networkwatcher_info: - tags: - - key1 - - key2 -''' - -RETURN = ''' -network_watchers: - description: - - The facts of the network watcher. - returned: always - type: complex - contains: - resource_group: - description: - - The resource group. - type: str - returned: always - sample: NetworkWatcherRG - id: - description: - - Resource ID. - returned: always - type: str - sample: "/subscriptions/xxx-xxx/resourceGroups/NetworkWatcherRG/providers/Microsoft.Network/networkWatchers/netwatcher_eastus" - location: - description: - - Resource location. - returned: always - type: str - sample: eastus - name: - description: - - Resource name. - returned: always - type: str - sample: mynetworkwatcher01 - tags: - description: - - Resource tags. - returned: always - type: dict - sample: { 'key1':'value1' } - type: - description: - - Resource type. - returned: always - type: str - sample: "Microsoft.Network/networkWatchers" - provisioning_state: - description: - - The provisioning state of the network watcher resource. - type: str - returned: always - sample: Succeeded -''' - -try: - from azure.core.exceptions import ResourceNotFoundError - from azure.mgmt.core.tools import parse_resource_id -except Exception: - # This is handled in azure_rm_common - pass - -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase - - -class AzureRMNetworkWatcherInfo(AzureRMModuleBase): - - def __init__(self): - - self.module_arg_spec = dict( - resource_group=dict(type='str'), - name=dict(type='str'), - tags=dict(type='list', elements='str') - ) - - self.results = dict( - changed=False, - network_watchers=[] - ) - - self.resource_group = None - self.name = None - self.tags = None - - super(AzureRMNetworkWatcherInfo, self).__init__(self.module_arg_spec, - supports_check_mode=True, - supports_tags=False, - facts_module=True) - - def exec_module(self, **kwargs): - for key in self.module_arg_spec: - setattr(self, key, kwargs[key]) - - if self.name and self.resource_group: - response = [self.get_by_name()] - elif self.resource_group: - response = self.list_by_resourcegroup() - else: - response = self.list_all() - - self.results['network_watchers'] = [self.to_dict(item) for item in response if response is not None] - - return self.results - - def get_by_name(self): - response = None - try: - response = self.network_client.network_watchers.get(self.resource_group, self.name) - - except ResourceNotFoundError as exec: - self.log("Failed to get network watchers, Exception as {0}".format(exec)) - - return response - - def list_by_resourcegroup(self): - response = None - try: - response = self.network_client.network_watchers.list(self.resource_group) - except Exception as exec: - self.log("Faild to list network watchers by resource group, exception as {0}".format(exec)) - return response - - def list_all(self): - response = None - try: - response = self.network_client.network_watchers.list_all() - except Exception as exc: - self.fail("Failed to list all items - {0}".format(str(exc))) - - return response - - def to_dict(self, body): - results = dict() - if body is not None and self.has_tags(body.tags, self.tags): - results = dict( - resource_group=parse_resource_id(body.id).get('resource_group'), - id=body.id, - name=body.name, - location=body.location, - tags=body.tags, - type=body.type, - provisioning_state=body.provisioning_state, - ) - return results - return None - - -def main(): - AzureRMNetworkWatcherInfo() - - -if __name__ == '__main__': - main() diff --git a/plugins/modules/azure_rm_openshiftmanagedclusterversion_info.py b/plugins/modules/azure_rm_openshiftmanagedclusterversion_info.py deleted file mode 100644 index eb240fc42..000000000 --- a/plugins/modules/azure_rm_openshiftmanagedclusterversion_info.py +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/python -# -# Copyright (c) 2020 Haiyuan Zhang -# -# 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 -__metaclass__ = type - - -DOCUMENTATION = ''' ---- -module: azure_rm_openshiftmanagedclusterversion_info -version_added: '2.5.0' -short_description: Fetch available versions of Azure Red Hat OpenShift Managed Cluster -description: - - fetch available version of Azure Red Hat OpenShift Managed Cluster instance. -options: - location: - description: - - List install versions available for the defined region. - required: true - type: str -extends_documentation_fragment: - - azure.azcollection.azure -author: - - Maxim Babushkin (@maxbab) -''' - -EXAMPLES = ''' -- name: Obtain openshift versions for ARO cluster - azure_rm_openshiftmanagedclusterversion_info: - location: centralus -''' - -RETURN = ''' -versions: - description: - - openshift versions values - returned: always - type: list -''' - -import json -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_rest import GenericRestClient - - -class Actions: - NoAction, Create, Update, Delete = range(4) - - -class AzureRMOpenShiftManagedClustersVersionInfo(AzureRMModuleBaseExt): - def __init__(self): - self.module_arg_spec = dict( - location=dict( - type='str', required=True - ) - ) - - self.location = None - - self.results = dict(changed=False) - self.mgmt_client = None - self.state = None - self.url = None - self.status_code = [200] - - self.query_parameters = {} - self.query_parameters['api-version'] = '2023-11-22' - self.header_parameters = {} - self.header_parameters['Content-Type'] = 'application/json; charset=utf-8' - - self.mgmt_client = None - super(AzureRMOpenShiftManagedClustersVersionInfo, self).__init__(self.module_arg_spec, supports_check_mode=True, supports_tags=False) - - def exec_module(self, **kwargs): - - for key in self.module_arg_spec: - setattr(self, key, kwargs[key]) - - self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - base_url=self._cloud_environment.endpoints.resource_manager) - self.results = self.get_versions() - return self.results - - def get_versions(self): - response = None - resp_results = {} - results = {} - # prepare url - self.url = ('/subscriptions' + - '/{{ subscription_id }}' + - '/providers' + - '/Microsoft.RedHatOpenShift' + - '/locations' + - '/{{ location }}' + - '/openshiftversions') - self.url = self.url.replace('{{ subscription_id }}', self.subscription_id) - self.url = self.url.replace('{{ location }}', self.location) - self.log("Fetch versions of openshift cluster.") - try: - response = self.mgmt_client.query(self.url, - 'GET', - self.query_parameters, - self.header_parameters, - None, - self.status_code, - 600, - 30) - if isinstance(response.text, str): - resp_results = json.loads(response.text) - else: - resp_results = json.loads(response.text()) - except Exception as e: - self.log('Could not get info for @(Model.ModuleOperationNameUpper).') - results['versions'] = self.format_versions(resp_results) - return results - - def format_versions(self, version): - result = list() - if version.get('value'): - for ver in version['value']: - result.append(ver.get('properties').get('version')) - return result - - -def main(): - AzureRMOpenShiftManagedClustersVersionInfo() - - -if __name__ == '__main__': - main() diff --git a/plugins/modules/azure_rm_snapshot.py b/plugins/modules/azure_rm_snapshot.py index 998bf9f00..b3db0a0d7 100644 --- a/plugins/modules/azure_rm_snapshot.py +++ b/plugins/modules/azure_rm_snapshot.py @@ -210,7 +210,7 @@ def __init__(self): self.body = {} self.body['properties'] = dict() self.query_parameters = {} - self.query_parameters['api-version'] = '2022-03-02' + self.query_parameters['api-version'] = '2019-03-01' self.header_parameters = {} self.header_parameters['Content-Type'] = 'application/json; charset=utf-8' @@ -233,8 +233,6 @@ def exec_module(self, **kwargs): self.body['properties']['creationData']['createOption'] = kwargs[key].get('create_option') self.body['properties']['creationData']['sourceUri'] = kwargs[key].get('source_uri') self.body['properties']['creationData']['sourceResourceId'] = kwargs[key].get('source_id') - if kwargs[key].get('source_uri') is not None: - self.query_parameters['api-version'] = '2019-03-01' else: self.body[key] = kwargs[key] diff --git a/plugins/modules/azure_rm_storageaccount.py b/plugins/modules/azure_rm_storageaccount.py index dbfce57e2..42c5b2e42 100644 --- a/plugins/modules/azure_rm_storageaccount.py +++ b/plugins/modules/azure_rm_storageaccount.py @@ -251,21 +251,6 @@ choices: - Enabled - Disabled - allow_cross_tenant_replication: - description: - - Allow or disallow cross AAD tenant object replication. - type: bool - allow_shared_key_access: - description: - - Indicates whether the storage account permits requests to be authorized with the account access key via Shared Key. - - If false, then all requests, including shared access signatures, must be authorized with Azure Active Directory (Azure AD). - - The default value is null, which is equivalent to true. - type: bool - default_to_o_auth_authentication: - description: - - A boolean flag which indicates whether the default authentication is OAuth or not. - - The default interpretation is false for this property. - type: bool encryption: description: - The encryption settings on the storage account. @@ -420,25 +405,6 @@ returned: always type: str sample: Standard_RAGRS - allow_cross_tenant_replication: - description: - - Allow or disallow cross AAD tenant object replication. - type: bool - returned: always - sample: true - allow_shared_key_access: - description: - - Indicates whether the storage account permits requests to be authorized with the account access key via Shared Key. - type: bool - returned: always - sample: true - default_to_o_auth_authentication: - description: - - A boolean flag which indicates whether the default authentication is OAuth or not. - - The default interpretation is false for this property. - type: bool - returned: always - sample: true custom_domain: description: - User domain assigned to the storage account. @@ -774,9 +740,6 @@ def __init__(self): minimum_tls_version=dict(type='str', choices=['TLS1_0', 'TLS1_1', 'TLS1_2']), public_network_access=dict(type='str', choices=['Enabled', 'Disabled']), allow_blob_public_access=dict(type='bool'), - allow_shared_key_access=dict(type='bool'), - allow_cross_tenant_replication=dict(type='bool'), - default_to_o_auth_authentication=dict(type='bool'), network_acls=dict(type='dict'), blob_cors=dict(type='list', options=cors_rule_spec, elements='dict'), static_website=dict(type='dict', options=static_website_spec), @@ -840,9 +803,6 @@ def __init__(self): self.is_hns_enabled = None self.large_file_shares_state = None self.enable_nfs_v3 = None - self.allow_shared_key_access = None - self.allow_cross_tenant_replication = None - self.default_to_o_auth_authentication = None super(AzureRMStorageAccount, self).__init__(self.module_arg_spec, supports_check_mode=True) @@ -945,9 +905,6 @@ def account_obj_to_dict(self, account_obj, blob_mgmt_props=None, blob_client_pro minimum_tls_version=account_obj.minimum_tls_version, public_network_access=account_obj.public_network_access, allow_blob_public_access=account_obj.allow_blob_public_access, - default_to_o_auth_authentication=account_obj.default_to_o_auth_authentication, - allow_cross_tenant_replication=account_obj.allow_cross_tenant_replication, - allow_shared_key_access=account_obj.allow_shared_key_access, network_acls=account_obj.network_rule_set, is_hns_enabled=account_obj.is_hns_enabled if account_obj.is_hns_enabled else False, enable_nfs_v3=account_obj.enable_nfs_v3 if hasattr(account_obj, 'enable_nfs_v3') else None, @@ -1161,43 +1118,6 @@ def update_account(self): except Exception as exc: self.fail("Failed to update allow public blob access: {0}".format(str(exc))) - if self.allow_shared_key_access is not None and self.allow_shared_key_access != self.account_dict.get('allow_shared_key_access'): - self.results['changed'] = True - self.account_dict['allow_shared_key_access'] = self.allow_shared_key_access - if not self.check_mode: - try: - parameters = self.storage_models.StorageAccountUpdateParameters(allow_shared_key_access=self.allow_shared_key_access) - self.storage_client.storage_accounts.update(self.resource_group, - self.name, - parameters) - except Exception as exc: - self.fail("Failed to update allow shared key access: {0}".format(str(exc))) - - if self.allow_cross_tenant_replication is not None and self.allow_cross_tenant_replication != self.account_dict.get('allow_cross_tenant_replication'): - self.results['changed'] = True - self.account_dict['allow_cross_tenant_replication'] = self.allow_cross_tenant_replication - if not self.check_mode: - try: - parameters = self.storage_models.StorageAccountUpdateParameters(allow_cross_tenant_replication=self.allow_cross_tenant_replication) - self.storage_client.storage_accounts.update(self.resource_group, - self.name, - parameters) - except Exception as exc: - self.fail("Failed to update allow cross tenant replication: {0}".format(str(exc))) - - if self.default_to_o_auth_authentication is not None and \ - self.default_to_o_auth_authentication != self.account_dict.get('default_to_o_auth_authentication'): - self.results['changed'] = True - self.account_dict['default_to_o_auth_authentication'] = self.default_to_o_auth_authentication - if not self.check_mode: - try: - parameters = self.storage_models.StorageAccountUpdateParameters(default_to_o_auth_authentication=self.default_to_o_auth_authentication) - self.storage_client.storage_accounts.update(self.resource_group, - self.name, - parameters) - except Exception as exc: - self.fail("Failed to update default_to_o_auth_authentication: {0}".format(str(exc))) - if self.account_type: if self.account_type != self.account_dict['sku_name']: # change the account type @@ -1338,9 +1258,6 @@ def create_account(self): is_hns_enabled=self.is_hns_enabled, enable_nfs_v3=self.enable_nfs_v3, large_file_shares_state=self.large_file_shares_state, - default_to_o_auth_authentication=self.default_to_o_auth_authentication, - allow_cross_tenant_replication=self.allow_cross_tenant_replication, - allow_shared_key_access=self.allow_shared_key_access, tags=dict() ) if self.tags: @@ -1368,9 +1285,6 @@ def create_account(self): is_hns_enabled=self.is_hns_enabled, enable_nfs_v3=self.enable_nfs_v3, access_tier=self.access_tier, - allow_shared_key_access=self.allow_shared_key_access, - default_to_o_auth_authentication=self.default_to_o_auth_authentication, - allow_cross_tenant_replication=self.allow_cross_tenant_replication, large_file_shares_state=self.large_file_shares_state) self.log(str(parameters)) try: diff --git a/plugins/modules/azure_rm_storageaccount_info.py b/plugins/modules/azure_rm_storageaccount_info.py index 38f7a1e00..a530459dd 100644 --- a/plugins/modules/azure_rm_storageaccount_info.py +++ b/plugins/modules/azure_rm_storageaccount_info.py @@ -138,25 +138,6 @@ returned: always type: str sample: Standard_ZRS - allow_cross_tenant_replication: - description: - - Allow or disallow cross AAD tenant object replication. - type: bool - returned: always - sample: true - allow_shared_key_access: - description: - - Indicates whether the storage account permits requests to be authorized with the account access key via Shared Key. - type: bool - returned: always - sample: true - default_to_o_auth_authentication: - description: - - A boolean flag which indicates whether the default authentication is OAuth or not. - - The default interpretation is false for this property. - type: bool - returned: always - sample: true custom_domain: description: - User domain assigned to the storage account. @@ -707,9 +688,6 @@ def account_obj_to_dict(self, account_obj): is_hns_enabled=account_obj.is_hns_enabled if account_obj.is_hns_enabled else False, large_file_shares_state=account_obj.large_file_shares_state, enable_nfs_v3=account_obj.enable_nfs_v3 if hasattr(account_obj, 'enable_nfs_v3') else None, - allow_cross_tenant_replication=account_obj.allow_cross_tenant_replication, - allow_shared_key_access=account_obj.allow_shared_key_access, - default_to_o_auth_authentication=account_obj.default_to_o_auth_authentication, static_website=dict( enabled=False, index_document=None, diff --git a/plugins/modules/azure_rm_virtualmachine.py b/plugins/modules/azure_rm_virtualmachine.py index 644290221..d11dbd185 100644 --- a/plugins/modules/azure_rm_virtualmachine.py +++ b/plugins/modules/azure_rm_virtualmachine.py @@ -159,39 +159,22 @@ description: - Name or ID of an existing availability set to add the VM to. The I(availability_set) should be in the same resource group as VM. type: str - capacity_reservation_group: - description: - - The name or ID of the capacity reservation group to be associated with. - type: dict - suboptions: - id: - description: - - The ID of the capacity reservation group to be associated with. - type: str - name: - description: - - The Name of the capacity reservation group to be associated with. - type: str - resource_group: - description: - - The resource group of capcacity reservation group to be associated with. - type: str proximity_placement_group: description: - - The name or ID of the proximity placement group to be associated with. + - The name or ID of the proximity placement group the VM should be associated with. type: dict suboptions: id: description: - - The ID of the proximity placement group to be associated with. + - The ID of the proximity placement group the VM should be associated with. type: str name: description: - - The Name of the proximity placement group to be associated with. + - The Name of the proximity placement group the VM should be associated with. type: str resource_group: description: - - The resource group of the proximity placement group to be associated with. + - The resource group of the proximity placement group the VM should be associated with. type: str storage_account_name: description: @@ -945,7 +928,6 @@ "proximityPlacementGroup": { "id": "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Compute/proximityPlacementGroups/testid13" }, - "CapacityReservation": {}, "hardwareProfile": { "vmSize": "Standard_D1" }, @@ -1089,6 +1071,7 @@ try: from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller + from azure.core.exceptions import ResourceNotFoundError from azure.mgmt.core.tools import parse_resource_id except ImportError: # This is handled in azure_rm_common @@ -1117,13 +1100,6 @@ def extract_names_from_blob_uri(blob_uri, storage_suffix): return extracted_names -capacity_reservation_group_spec = dict( - id=dict(type='str'), - name=dict(type='str'), - resource_group=dict(type='str') -) - - proximity_placement_group_spec = dict( id=dict(type='str'), name=dict(type='str'), @@ -1182,7 +1158,6 @@ def __init__(self): managed_disk_type=dict(type='str', choices=['Standard_LRS', 'StandardSSD_LRS', 'StandardSSD_ZRS', 'Premium_LRS', 'Premium_ZRS', 'UltraSSD_LRS']), os_disk_name=dict(type='str'), proximity_placement_group=dict(type='dict', options=proximity_placement_group_spec), - capacity_reservation_group=dict(type='dict', options=capacity_reservation_group_spec), os_type=dict(type='str', choices=['Linux', 'Windows'], default='Linux'), public_ip_allocation_method=dict(type='str', choices=['Dynamic', 'Static', 'Disabled'], default='Static', aliases=['public_ip_allocation']), @@ -1284,7 +1259,6 @@ def __init__(self): self.managed_disk_type = None self.os_disk_name = None self.proximity_placement_group = None - self.capacity_reservation_group = None self.network_interface_names = None self.remove_on_absent = set() self.tags = None @@ -1447,7 +1421,7 @@ def exec_module(self, **kwargs): elif self.image.get('id'): try: image_reference = self.compute_models.ImageReference(id=self.image['id']) - except Exception: + except Exception as exc: self.fail("id Error: Cannot get image from the reference id - {0}".format(self.image['id'])) else: self.fail("parameter error: expecting image to contain [publisher, offer, sku, version], [name, resource_group] or [id]") @@ -1759,29 +1733,6 @@ def exec_module(self, **kwargs): else: self.fail("Parameter error: Please recheck your proximity placement group ") - if self.capacity_reservation_group is not None: - if vm_dict.get('capacity_reservation') is None: - changed = True - differences.append('capacity_reservation_group') - if self.capacity_reservation_group.get('name') is not None and self.capacity_reservation_group.get('resource_group') is not None: - capacity_reservation_group = self.get_capacity_reservation_group(self.capacity_reservation_group.get('resource_group'), - self.capacity_reservation_group.get('name')) - self.capacity_reservation_group['id'] = capacity_reservation_group.id - - elif self.capacity_reservation_group.get('id') is not None: - if vm_dict['capacity_reservation'].get('id', "").lower() != self.capacity_reservation_group['id'].lower(): - changed = True - differences.append('capacity_reservation_group') - elif self.capacity_reservation_group.get('name') is not None and self.capacity_reservation_group.get('resource_group') is not None: - capacity_reservation_group = self.get_capacity_reservation_group(self.capacity_reservation_group.get('resource_group'), - self.capacity_reservation_group.get('name')) - if vm_dict['capacity_reservation'].get('id', "").lower() != capacity_reservation_group.id.lower(): - changed = True - differences.append('capacity_reservation_group') - self.capacity_reservation_group['id'] = capacity_reservation_group.id - else: - self.fail("Parameter error: Please recheck your capacity reservation group ") - self.differences = differences elif self.state == 'absent': @@ -1841,17 +1792,6 @@ def exec_module(self, **kwargs): else: self.fail("Parameter error: Please recheck your proximity placement group ") - capacity_reservation_group_resource = None - if self.capacity_reservation_group is not None: - if self.capacity_reservation_group.get('id') is not None: - capacity_reservation_group_resource = self.compute_models.SubResource(id=self.capacity_reservation_group['id']) - elif self.capacity_reservation_group.get('name') is not None and self.capacity_reservation_group.get('resource_group') is not None: - capacity_reservation_group = self.get_capacity_reservation_group(self.capacity_reservation_group.get('resource_group'), - self.capacity_reservation_group.get('name')) - capacity_reservation_group_resource = self.compute_models.SubResource(id=capacity_reservation_group.id) - else: - self.fail("Parameter error: Please recheck your capacity reservation group ") - # Get defaults if not self.network_interface_names: default_nic = self.create_default_nic() @@ -1934,7 +1874,6 @@ def exec_module(self, **kwargs): ), availability_set=availability_set_resource, proximity_placement_group=proximity_placement_group_resource, - capacity_reservation=self.compute_models.CapacityReservationProfile(capacity_reservation_group=capacity_reservation_group_resource), plan=plan, zones=self.zones, ) @@ -2167,20 +2106,6 @@ def exec_module(self, **kwargs): # pass if the proximity Placement Group pass - capacity_reservation_group_resource = None - if self.capacity_reservation_group is not None: - try: - capacity_reservation_group_resource = self.compute_models.SubResource(id=self.capacity_reservation_group.get('id')) - except Exception: - # pass if the proximity Placement Group - pass - else: - try: - capacity_reservation_group_resource = self.compute_models.SubResource(id=vm_dict['capacity_reservation_group'].get('id')) - except Exception: - # pass if the proximity Placement Group - pass - availability_set_resource = None try: availability_set_resource = self.compute_models.SubResource(id=vm_dict['availability_set'].get('id')) @@ -2223,7 +2148,6 @@ def exec_module(self, **kwargs): ), availability_set=availability_set_resource, proximity_placement_group=proximity_placement_group_resource, - capacity_reservation=self.compute_models.CapacityReservationProfile(capacity_reservation_group=capacity_reservation_group_resource), network_profile=self.compute_models.NetworkProfile( network_interfaces=nics ) @@ -2466,7 +2390,7 @@ def get_os_disk(self, os_disk): os_disk['managed_disk'] = dict(id=response.id) os_disk['create_option'] = response.creation_data.create_option return os_disk - except Exception: + except Exception as ec: self.fail('Could not find os disk {0} in resource group {1}'.format(os_disk_name, resource_group_name)) def get_vm(self): @@ -2819,12 +2743,6 @@ def get_custom_image_reference(self, name, resource_group=None): self.fail("Error could not find image with name {0}".format(name)) return None - def get_capacity_reservation_group(self, resource_group, name): - try: - return self.compute_client.capacity_reservation_groups.get(resource_group, name) - except Exception as exc: - self.fail("Error fetching capacity reservation group {0} - {1}".format(name, str(exc))) - def get_proximity_placement_group(self, resource_group, name): try: return self.compute_client.proximity_placement_groups.get(resource_group, name) diff --git a/plugins/modules/azure_rm_virtualmachine_info.py b/plugins/modules/azure_rm_virtualmachine_info.py index 96dd21ab9..3df8e2fbc 100644 --- a/plugins/modules/azure_rm_virtualmachine_info.py +++ b/plugins/modules/azure_rm_virtualmachine_info.py @@ -220,12 +220,6 @@ type: dict returned: always sample: { "id": "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Compute/proximityPlacementGroups/testid13"} - CapacityReservation: - description: - - The name or ID of the capacity reservation group to be associated with. - type: dict - returned: always - sample: { } os_disk_caching: description: - Type of OS disk caching. @@ -504,13 +498,9 @@ def serialize_vm(self, vm): new_result['state'] = 'present' new_result['location'] = vm.location new_result['vm_size'] = result['hardware_profile']['vm_size'] - new_result['proximityPlacementGroup'] = result.get('proximity_placement_group') new_result['zones'] = result.get('zones', None) new_result['additional_capabilities'] = result.get('additional_capabilities') - new_result['capacity_reservation'] = dict() - if result.get('capacity_reservation') is not None: - new_result['capacity_reservation']['capacity_reservation_group'] = result.get('capacity_reservation').as_dict() os_profile = result.get('os_profile') if os_profile is not None: new_result['admin_username'] = os_profile.get('admin_username') diff --git a/plugins/modules/azure_rm_virtualmachinescaleset.py b/plugins/modules/azure_rm_virtualmachinescaleset.py index 1c488324c..c4211a971 100644 --- a/plugins/modules/azure_rm_virtualmachinescaleset.py +++ b/plugins/modules/azure_rm_virtualmachinescaleset.py @@ -122,42 +122,6 @@ Set C(key_data) to the actual value of the public key. type: list elements: dict - identity: - description: - - Identity for this resource. - type: dict - version_added: '2.5.0' - suboptions: - type: - description: - - Type of the managed identity - choices: - - SystemAssigned - - UserAssigned - - SystemAssigned, UserAssigned - - 'None' - default: 'None' - type: str - user_assigned_identities: - description: - - User Assigned Managed Identities and its options - required: false - type: dict - default: {} - suboptions: - id: - description: - - List of the user assigned IDs associated to this resource - required: false - type: list - elements: str - default: [] - append: - description: - - If the list of identities has to be appended to current identities (true) or if it has to replace current identities (false) - required: false - type: bool - default: True image: description: - Specifies the image used to build the VM. @@ -689,14 +653,12 @@ from azure.core.exceptions import ResourceNotFoundError from azure.mgmt.core.tools import parse_resource_id from azure.core.exceptions import ResourceNotFoundError - from azure.mgmt.compute.models import (VirtualMachineScaleSetIdentity, UserAssignedIdentitiesValue) except ImportError: # This is handled in azure_rm_common pass -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import azure_id_to_dict, format_resource_id -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, azure_id_to_dict, format_resource_id from ansible.module_utils.basic import to_native, to_bytes @@ -705,37 +667,7 @@ AZURE_ENUM_MODULES = ['azure.mgmt.compute.models'] -user_assigned_identities_spec = dict( - id=dict( - type='list', - default=[], - elements='str' - ), - append=dict( - type='bool', - default=True - ) -) - - -managed_identity_spec = dict( - type=dict( - type='str', - choices=['SystemAssigned', - 'UserAssigned', - 'SystemAssigned, UserAssigned', - 'None'], - default='None' - ), - user_assigned_identities=dict( - type='dict', - options=user_assigned_identities_spec, - default={} - ), -) - - -class AzureRMVirtualMachineScaleSet(AzureRMModuleBaseExt): +class AzureRMVirtualMachineScaleSet(AzureRMModuleBase): def __init__(self): @@ -812,10 +744,6 @@ def __init__(self): ) ) ), - identity=dict( - type='dict', - options=managed_identity_spec - ), ) self.resource_group = None @@ -858,8 +786,6 @@ def __init__(self): self.orchestration_mode = None self.os_disk_size_gb = None self.security_profile = None - self._managed_identity = None - self.identity = None mutually_exclusive = [('load_balancer', 'application_gateway')] self.results = dict( @@ -873,14 +799,6 @@ def __init__(self): supports_check_mode=True, mutually_exclusive=mutually_exclusive) - @property - def managed_identity(self): - if not self._managed_identity: - self._managed_identity = {"identity": VirtualMachineScaleSetIdentity, - "user_assigned": UserAssignedIdentitiesValue - } - return self._managed_identity - def exec_module(self, **kwargs): for key in list(self.module_arg_spec.keys()) + ['tags']: @@ -1058,12 +976,6 @@ def exec_module(self, **kwargs): changed = True vmss_dict['virtual_machine_profile']['storage_profile']['image_reference'] = image_reference.as_dict() - if self.identity: - update_identity, self.identity = self.update_identities(vmss_dict.get('identity', dict())) - if update_identity: - differences.append('Identity') - changed = True - update_tags, vmss_dict['tags'] = self.update_tags(vmss_dict.get('tags', dict())) if update_tags: differences.append('Tags') @@ -1186,8 +1098,6 @@ def exec_module(self, **kwargs): if self.state == 'present': self.log("CHANGED: virtual machine scale set {0} does not exist but state is 'present'.".format(self.name)) changed = True - if self.identity: - update_identity, self.identity = self.update_identities(dict()) self.results['changed'] = changed self.results['ansible_facts']['azure_vmss'] = results @@ -1299,9 +1209,6 @@ def exec_module(self, **kwargs): zones=self.zones ) - if self.identity: - vmss_resource.identity = self.identity - if self.priority == 'Spot': vmss_resource.virtual_machine_profile.priority = self.priority vmss_resource.virtual_machine_profile.eviction_policy = self.eviction_policy @@ -1446,9 +1353,6 @@ def exec_module(self, **kwargs): if self.terminate_event_timeout_minutes: vmss_resource.virtual_machine_profile.scheduled_events_profile = self.gen_scheduled_event_profile() - if self.identity: - vmss_resource.identity = self.identity - if image_reference is not None: vmss_resource.virtual_machine_profile.storage_profile.image_reference = image_reference diff --git a/plugins/modules/azure_rm_virtualmachinescaleset_info.py b/plugins/modules/azure_rm_virtualmachinescaleset_info.py index 461afe4ed..642f6b58d 100644 --- a/plugins/modules/azure_rm_virtualmachinescaleset_info.py +++ b/plugins/modules/azure_rm_virtualmachinescaleset_info.py @@ -126,30 +126,6 @@ returned: always type: str sample: Standard_LRS - identity: - description: - - Identity for the Server. - type: complex - returned: when available - contains: - type: - description: - - Type of the managed identity - returned: always - sample: UserAssigned - type: str - user_assigned_identities: - description: - - User Assigned Managed Identities and its options - returned: always - type: complex - contains: - id: - description: - - Dict of the user assigned identities IDs associated to the Resource - returned: always - type: dict - elements: dict image: description: - Image specification. @@ -412,7 +388,6 @@ def exec_module(self, **kwargs): 'virtual_network_name': virtual_network_name, 'subnet_name': subnet_name, 'load_balancer': load_balancer_name, - 'identity': vmss.get('identity', None), 'tags': vmss.get('tags') } diff --git a/pr-pipelines.yml b/pr-pipelines.yml index 141bac482..5074abc4e 100644 --- a/pr-pipelines.yml +++ b/pr-pipelines.yml @@ -35,6 +35,7 @@ parameters: - "azure_rm_acs" - "azure_rm_adgroup" - "azure_rm_aduser" + - "azure_rm_afdorigin" - "azure_rm_afdendpoint" - "azure_rm_aks" - "azure_rm_aksagentpool" diff --git a/release-pipelines.yml b/release-pipelines.yml index d583e814a..212de7665 100644 --- a/release-pipelines.yml +++ b/release-pipelines.yml @@ -16,7 +16,7 @@ pool: steps: - script: | pip install wheel - pip install ansible==v2.15.0 + pip install ansible==v2.14.0 ansible --version displayName: 'install ansible' diff --git a/requirements.txt b/requirements.txt index d4774b8bb..557c59e47 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,13 +2,13 @@ packaging requests[security] xmltodict msgraph-sdk==1.0.0 -azure-cli-core==2.61.0 +azure-cli-core==2.34.0 azure-common==1.1.11 -azure-identity==1.16.1 +azure-identity==1.14.0 azure-mgmt-authorization==2.0.0 azure-mgmt-apimanagement==3.0.0 azure-mgmt-batch==16.2.0 -azure-mgmt-cdn==13.1.1 +azure-mgmt-cdn==11.0.0 azure-mgmt-compute==30.6.0 azure-mgmt-containerinstance==9.0.0 azure-mgmt-core==1.4.0 @@ -34,7 +34,7 @@ azure-mgmt-storage==19.0.0 azure-mgmt-trafficmanager==1.0.0b1 azure-mgmt-web==6.1.0 azure-nspkg==2.0.0 -azure-storage-blob==12.13.0 +azure-storage-blob==12.11.0 azure-core==1.28.0 azure-keyvault==4.2.0 azure-mgmt-keyvault==10.0.0 @@ -44,7 +44,7 @@ azure-mgmt-devtestlabs==9.0.0 azure-mgmt-loganalytics==12.0.0 azure-mgmt-automation==1.0.0 azure-mgmt-iothub==2.2.0 -azure-iot-hub==2.6.1;platform_machine=="x86_64" +azure-iot-hub==2.6.1 azure-mgmt-recoveryservices==2.0.0 azure-mgmt-recoveryservicesbackup==3.0.0 azure-mgmt-notificationhubs==7.0.0 diff --git a/tests/integration/targets/azure_rm_afdendpoint/tasks/main.yml b/tests/integration/targets/azure_rm_afdendpoint/tasks/main.yml deleted file mode 100644 index 8816af29e..000000000 --- a/tests/integration/targets/azure_rm_afdendpoint/tasks/main.yml +++ /dev/null @@ -1,168 +0,0 @@ -- name: Prepare random name for Profile & EndPoint - ansible.builtin.set_fact: - profile: "prof-{{ resource_group | hash('md5') | truncate(4, True, '') }}{{ 100000 | random }}" - endpoint: "endpoint-{{ resource_group | hash('md5') | truncate(4, True, '') }}{{ 100000 | random }}" - -- name: Create Standard Frontdoor Profile - azure_rm_cdnprofile: - name: "{{ profile }}" - location: "Global" - resource_group: "{{ resource_group }}" - sku: "standard_azurefrontdoor" - state: "present" - -- name: Create EndPoint - azure_rm_afdendpoint: - name: "{{ endpoint }}" - profile_name: "{{ profile }}" - resource_group: "{{ resource_group }}" - enabled_state: "Enabled" - auto_generated_domain_name_label_scope: "TenantReuse" - tags: - test: "tag value" - state: "present" - register: output - -- name: Assert the resource was created and returns expected variables - ansible.builtin.assert: - that: - - output.changed - - output.id - - output.host_name - -- name: Update EndPoint (idempotent test) - azure_rm_afdendpoint: - name: "{{ endpoint }}" - profile_name: "{{ profile }}" - resource_group: "{{ resource_group }}" - enabled_state: "Enabled" - auto_generated_domain_name_label_scope: "TenantReuse" - tags: - test: "tag value" - state: "present" - register: output - -- name: Assert the resource has not changed - ansible.builtin.assert: - that: - - not output.changed - -- name: Load Endpoint info - azure_rm_afdendpoint_info: - name: "{{ endpoint }}" - profile_name: "{{ profile }}" - resource_group: "{{ resource_group }}" - register: output - -- name: Assert the resource has the proper values set - ansible.builtin.assert: - that: - - output.afdendpoints | length == 1 - - output.afdendpoints[0].auto_generated_domain_name_label_scope == 'TenantReuse' - - output.afdendpoints[0].enabled_state == 'Enabled' - - output.afdendpoints[0].host_name - - output.afdendpoints[0].id - - output.afdendpoints[0].profile_name == profile - - output.afdendpoints[0].tags.test == 'tag value' - - not output.changed - -- name: Update EndPoint (with different values) - azure_rm_afdendpoint: - name: "{{ endpoint }}" - profile_name: "{{ profile }}" - resource_group: "{{ resource_group }}" - enabled_state: "Disabled" - tags: - test: "new tag value" - newtag: "another value" - state: "present" - register: output - -- name: Assert the resource has changed - ansible.builtin.assert: - that: - - output.changed - -- name: Update EndPoint (idempotent test) - azure_rm_afdendpoint: - name: "{{ endpoint }}" - profile_name: "{{ profile }}" - resource_group: "{{ resource_group }}" - enabled_state: "Disabled" - tags: - test: "new tag value" - newtag: "another value" - state: "present" - register: output - -- name: Assert the resource has not changed - ansible.builtin.assert: - that: - - not output.changed - -- name: Update EndPoint (replace tags) - azure_rm_afdendpoint: - name: "{{ endpoint }}" - profile_name: "{{ profile }}" - resource_group: "{{ resource_group }}" - enabled_state: "Disabled" - append_tags: false - tags: - test2: "a tag value" - state: "present" - register: output - -- name: Assert the resource has changed - ansible.builtin.assert: - that: - - output.changed - -- name: Load Endpoint info - azure_rm_afdendpoint_info: - name: "{{ endpoint }}" - profile_name: "{{ profile }}" - resource_group: "{{ resource_group }}" - register: output - -- name: Assert the resource has the proper values set and is missing the previous tag - ansible.builtin.assert: - that: - - output.afdendpoints | length == 1 - - output.afdendpoints[0].auto_generated_domain_name_label_scope == 'TenantReuse' - - output.afdendpoints[0].enabled_state == 'Disabled' - - output.afdendpoints[0].tags['test2'] == 'a tag value' - - output.afdendpoints[0].tags['newtag'] is not defined - - not output.changed - -- name: Delete EndPoint - azure_rm_afdendpoint: - name: "{{ endpoint }}" - profile_name: "{{ profile }}" - resource_group: "{{ resource_group }}" - state: "absent" - register: output - -- name: Assert the resource was deleted - ansible.builtin.assert: - that: - - output.changed - -- name: Delete EndPoint (idempotent test) - azure_rm_afdendpoint: - name: "{{ endpoint }}" - profile_name: "{{ profile }}" - resource_group: "{{ resource_group }}" - state: "absent" - register: output - -- name: Assert the delete function is idempotent - ansible.builtin.assert: - that: - - not output.changed - -- name: Delete Frontdoor Profile - azure_rm_cdnprofile: - name: "{{ profile }}" - location: "Global" - resource_group: "{{ resource_group }}" - state: "absent" diff --git a/tests/integration/targets/azure_rm_afdendpoint/aliases b/tests/integration/targets/azure_rm_afdorigin/aliases similarity index 100% rename from tests/integration/targets/azure_rm_afdendpoint/aliases rename to tests/integration/targets/azure_rm_afdorigin/aliases diff --git a/tests/integration/targets/azure_rm_afdendpoint/meta/main.yml b/tests/integration/targets/azure_rm_afdorigin/meta/main.yml similarity index 100% rename from tests/integration/targets/azure_rm_afdendpoint/meta/main.yml rename to tests/integration/targets/azure_rm_afdorigin/meta/main.yml diff --git a/tests/integration/targets/azure_rm_afdorigin/tasks/main.yml b/tests/integration/targets/azure_rm_afdorigin/tasks/main.yml new file mode 100644 index 000000000..d60536c41 --- /dev/null +++ b/tests/integration/targets/azure_rm_afdorigin/tasks/main.yml @@ -0,0 +1,223 @@ +- name: Prepare random name for Profile & EndPoint & Origin Group & Origin + ansible.builtin.set_fact: + profile: "prof-{{ resource_group | hash('md5') | truncate(4, True, '') }}{{ 100000 | random }}" + origin_group: "origin-group-{{ resource_group | hash('md5') | truncate(4, True, '') }}{{ 100000 | random }}" + origin: "origin-{{ resource_group | hash('md5') | truncate(4, True, '') }}{{ 100000 | random }}" + origin2: "origin2-{{ resource_group | hash('md5') | truncate(4, True, '') }}{{ 100000 | random }}" + +- name: Create Standard Frontdoor Profile + azure_rm_cdnprofile: + name: "{{ profile }}" + location: "Global" + resource_group: "{{ resource_group }}" + sku: "standard_azurefrontdoor" + state: "present" + +- name: Create Origin Group + azure_rm_afdorigingroup: + name: "{{ origin_group }}" + profile_name: "{{ profile }}" + resource_group: "{{ resource_group }}" + state: "present" + health_probe_settings: + probe_interval_in_seconds: 100 + probe_path: "/" + probe_protocol: "Https" + probe_request_type: "HEAD" + load_balancing_settings: + additional_latency_in_milliseconds: 50 + sample_size: 4 + successful_samples_required: 3 + register: output + +- name: Create Origin + azure_rm_afdorigin: + name: "{{ origin }}" + origin_group_name: "{{ origin_group }}" + profile_name: "{{ profile }}" + resource_group: "{{ resource_group }}" + state: "present" + host_name: "10.0.0.1" + origin_host_header: "10.0.0.1" + http_port: 80 + https_port: 443 + priority: 1 + weight: 123 + register: output + +- name: Assert the resource was created + ansible.builtin.assert: + that: + - output.changed + - output.id + +- name: Update Origin (idempotent test) + azure_rm_afdorigin: + name: "{{ origin }}" + origin_group_name: "{{ origin_group }}" + profile_name: "{{ profile }}" + resource_group: "{{ resource_group }}" + state: "present" + host_name: "10.0.0.1" + origin_host_header: "10.0.0.1" + http_port: 80 + https_port: 443 + priority: 1 + weight: 123 + register: output + +- name: Assert the resource was not changed + ansible.builtin.assert: + that: + - not output.changed + +- name: Load Origin info + azure_rm_afdorigin_info: + name: "{{ origin }}" + origin_group_name: "{{ origin_group }}" + profile_name: "{{ profile }}" + resource_group: "{{ resource_group }}" + register: output + +- name: Assert the resource has the proper values set + ansible.builtin.assert: + that: + - output.afdorigins | length == 1 + - output.afdorigins[0].enabled_state == 'Enabled' + - output.afdorigins[0].host_name == '10.0.0.1' + - output.afdorigins[0].http_port == 80 + - output.afdorigins[0].https_port == 443 + - output.afdorigins[0].id + - output.afdorigins[0].origin_host_header == '10.0.0.1' + - output.afdorigins[0].priority == 1 + - output.afdorigins[0].weight == 123 + - not output.changed + +- name: Create Origin 2 + azure_rm_afdorigin: + name: "{{ origin2 }}" + origin_group_name: "{{ origin_group }}" + profile_name: "{{ profile }}" + resource_group: "{{ resource_group }}" + state: "present" + host_name: "10.0.1.2" + origin_host_header: "10.0.1.2" + http_port: 80 + https_port: 443 + priority: 2 + weight: 234 + register: output + +- name: Assert the resource was created + ansible.builtin.assert: + that: + - output.changed + - output.id + +- name: Load Origin info for both + azure_rm_afdorigin_info: + origin_group_name: "{{ origin_group }}" + profile_name: "{{ profile }}" + resource_group: "{{ resource_group }}" + register: output + +- name: Assert the resource has the proper values set + ansible.builtin.assert: + that: + - output.afdorigins | length == 2 + - not output.changed + +- name: Update Origin (with different values) + azure_rm_afdorigin: + name: "{{ origin }}" + origin_group_name: "{{ origin_group }}" + profile_name: "{{ profile }}" + resource_group: "{{ resource_group }}" + state: "present" + host_name: "10.0.0.2" + origin_host_header: "10.0.0.2" + http_port: 8080 + priority: 1 + weight: 111 + register: output + +- name: Assert the resource was changed + ansible.builtin.assert: + that: + - output.changed + +- name: Update Origin Group (idempotent test) + azure_rm_afdorigin: + name: "{{ origin }}" + origin_group_name: "{{ origin_group }}" + profile_name: "{{ profile }}" + resource_group: "{{ resource_group }}" + state: "present" + host_name: "10.0.0.2" + origin_host_header: "10.0.0.2" + http_port: 8080 + priority: 1 + weight: 111 + register: output + +- name: Assert the resource was not changed + ansible.builtin.assert: + that: + - not output.changed + +- name: Delete Origin + azure_rm_afdorigin: + name: "{{ origin }}" + origin_group_name: "{{ origin_group }}" + profile_name: "{{ profile }}" + resource_group: "{{ resource_group }}" + state: "absent" + register: output + +- name: Assert the resource was deleted + ansible.builtin.assert: + that: + - output.changed + +- name: Delete Origin 2 + azure_rm_afdorigin: + name: "{{ origin2 }}" + origin_group_name: "{{ origin_group }}" + profile_name: "{{ profile }}" + resource_group: "{{ resource_group }}" + state: "absent" + register: output + +- name: Assert the resource was delete + ansible.builtin.assert: + that: + - output.changed + +- name: Delete Origin (idempotent test) + azure_rm_afdorigin: + name: "{{ origin }}" + origin_group_name: "{{ origin_group }}" + profile_name: "{{ profile }}" + resource_group: "{{ resource_group }}" + state: "absent" + register: output + +- name: Assert the resource was not changed + ansible.builtin.assert: + that: + - not output.changed + +- name: Delete Origin Group + azure_rm_afdorigingroup: + name: "{{ origin_group }}" + profile_name: "{{ profile }}" + resource_group: "{{ resource_group }}" + state: "absent" + register: output + +- name: Delete Frontdoor Profile + azure_rm_cdnprofile: + name: "{{ profile }}" + location: "Global" + resource_group: "{{ resource_group }}" + state: "absent" diff --git a/tests/integration/targets/azure_rm_appgateway/tasks/main.yml b/tests/integration/targets/azure_rm_appgateway/tasks/main.yml index 17142ab4a..b5584d2f5 100644 --- a/tests/integration/targets/azure_rm_appgateway/tasks/main.yml +++ b/tests/integration/targets/azure_rm_appgateway/tasks/main.yml @@ -1,81 +1,1112 @@ -- name: Gather Resource Group info - azure.azcollection.azure_rm_resourcegroup_info: - name: "{{ resource_group }}" - register: __rg_info - - name: Prepare random number ansible.builtin.set_fact: rpfx: "{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}" cert1_file: "cert1.txt" cert2_file: "cert2.txt" cert3b64_file: "cert3b64.txt" - location: "{{ __rg_info.resourcegroups.0.location }}" run_once: true - name: Set json query to only retrieve gateways from this test ansible.builtin.set_fact: query: "[?ends_with(name, `{{ rpfx }}`)]" run_once: true -- name: Create User Managed Identities - azure_rm_resource: +- name: Load app gateways + azure_rm_appgateway_info: + register: appgw_output +- name: Assert there are no gateways + ansible.builtin.assert: + that: + - appgw_output.gateways | community.general.json_query(query) | length == 0 + +- name: Create a virtual network + azure_rm_virtualnetwork: + name: vnet{{ rpfx }} resource_group: "{{ resource_group }}" - provider: ManagedIdentity - resource_type: userAssignedIdentities - resource_name: "{{ item }}" - api_version: "2023-01-31" - body: - location: "{{ location }}" - state: present - loop: - - "ansible-test-appgw-identity" - - "ansible-test-appgw-identity-2" + address_prefixes_cidr: + - 10.1.0.0/16 + - 172.100.0.0/16 + dns_servers: + - 127.0.0.1 + - 127.0.0.2 + register: vnet_output +- name: Create a subnet + azure_rm_subnet: + name: subnet{{ rpfx }} + virtual_network_name: vnet{{ rpfx }} + resource_group: "{{ resource_group }}" + address_prefix_cidr: 10.1.0.0/24 + register: subnet_output -- name: Set identities IDs to test. Identities ansible-test-appgw-identity and ansible-test-appgw-identity-2 have to be created previously - ansible.builtin.set_fact: - user_identity_1: "/subscriptions/{{ azure_subscription_id }}/resourcegroups/{{ resource_group }}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/ansible-test-appgw-identity" - user_identity_2: "/subscriptions/{{ azure_subscription_id }}/resourcegroups/{{ resource_group }}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/ansible-test-appgw-identity-2" +- name: Create instance of Application Gateway -- check mode + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway{{ rpfx }}" + sku: + name: standard_small + tier: standard + capacity: 2 + ssl_policy: + policy_type: predefined + policy_name: ssl_policy20150501 + authentication_certificates: + - name: cert1 + data: "{{ lookup('file', cert1_file) }}" + ssl_certificates: + - name: cert2 + password: your-password + data: "{{ lookup('file', cert2_file) }}" + gateway_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: app_gateway_ip_config + frontend_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: sample_gateway_frontend_ip_config + frontend_ports: + - port: 90 + name: ag_frontend_port + - port: 80 + name: http_frontend_port + backend_address_pools: + - backend_addresses: + - ip_address: 10.0.0.4 + name: test_backend_address_pool + probes: + - name: custom_probe + protocol: http + host: 10.0.0.4 + path: /healthz + interval: 30 + timeout: 30 + unhealthy_threshold: 3 + backend_http_settings_collection: + - port: 80 + protocol: http + cookie_based_affinity: enabled + probe: custom_probe + name: sample_appgateway_http_settings + http_listeners: + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: ag_frontend_port + protocol: https + ssl_certificate: cert2 + name: sample_http_listener + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: http_frontend_port + protocol: http + name: http_listener + request_routing_rules: + - rule_type: basic + backend_address_pool: test_backend_address_pool + backend_http_settings: sample_appgateway_http_settings + http_listener: sample_http_listener + name: rule1 + - rule_type: basic + http_listener: http_listener + redirect_configuration: redirect_site_to_https + name: http_redirect_rule + redirect_configurations: + - redirect_type: permanent + target_listener: sample_http_listener + include_path: true + include_query_string: true + name: redirect_site_to_https + register: output + check_mode: true +- name: Assert the resource instance is well created + ansible.builtin.assert: + that: + - output.changed + +- name: Create instance of application gateway + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway{{ rpfx }}" + sku: + name: standard_small + tier: standard + capacity: 2 + ssl_policy: + policy_type: predefined + policy_name: ssl_policy20150501 + authentication_certificates: + - name: cert1 + data: "{{ lookup('file', cert1_file) }}" + ssl_certificates: + - name: cert2 + password: your-password + data: "{{ lookup('file', cert2_file) }}" + gateway_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: app_gateway_ip_config + frontend_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: sample_gateway_frontend_ip_config + frontend_ports: + - port: 90 + name: ag_frontend_port + - port: 80 + name: http_frontend_port + backend_address_pools: + - backend_addresses: + - ip_address: 10.0.0.4 + name: test_backend_address_pool + probes: + - name: custom_probe + protocol: http + host: 10.0.0.4 + path: /healthz + interval: 30 + timeout: 30 + unhealthy_threshold: 3 + backend_http_settings_collection: + - port: 80 + protocol: http + cookie_based_affinity: enabled + probe: custom_probe + name: sample_appgateway_http_settings + http_listeners: + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: ag_frontend_port + protocol: https + ssl_certificate: cert2 + name: sample_http_listener + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: http_frontend_port + protocol: http + name: http_listener + request_routing_rules: + - rule_type: basic + backend_address_pool: test_backend_address_pool + backend_http_settings: sample_appgateway_http_settings + http_listener: sample_http_listener + name: rule1 + - rule_type: basic + http_listener: http_listener + redirect_configuration: redirect_site_to_https + name: http_redirect_rule + redirect_configurations: + - redirect_type: permanent + target_listener: sample_http_listener + include_path: true + include_query_string: true + name: redirect_site_to_https + register: output +- name: Assert the resource instance is well created + ansible.builtin.assert: + that: + - output.changed + +- name: Load app gateway + azure_rm_appgateway_info: + name: "appgateway{{ rpfx }}" + resource_group: "{{ resource_group }}" + register: output +- name: Assert properties + ansible.builtin.assert: + that: + - output.gateways | length == 1 + - output.gateways[0].name == 'appgateway{{ rpfx }}' + - output.gateways[0].ssl_policy + - output.gateways[0].ssl_policy.policy_type == 'predefined' + - output.gateways[0].ssl_policy.policy_name == 'ssl_policy20150501' + +- name: Stop instance of Application Gateway -- check mode + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway{{ rpfx }}" + gateway_state: stopped + check_mode: true + register: output +- name: Assert the resource instance is stopped + ansible.builtin.assert: + that: + - output.changed + +- name: Stop instance of Application Gateway + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway{{ rpfx }}" + gateway_state: stopped + register: output +- name: Assert the resource instance is stopped + ansible.builtin.assert: + that: + - output.changed + - output.operational_state == 'Stopped' + +- name: Stop already stopped instance of Application Gateway + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway{{ rpfx }}" + gateway_state: stopped + register: output +- name: Assert the resource instance did not change + ansible.builtin.assert: + that: + - not output.changed + - output.operational_state == 'Stopped' + +- name: Start instance of Application Gateway -- check mode + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway{{ rpfx }}" + gateway_state: started + check_mode: true + register: output +- name: Assert the resource instance is started + ansible.builtin.assert: + that: + - output.changed + +- name: Start instance of Application Gateway + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway{{ rpfx }}" + gateway_state: started + register: output +- name: Assert the resource instance is started + ansible.builtin.assert: + that: + - output.changed + - output.operational_state == 'Running' + +- name: Start already started instance of Application Gateway + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway{{ rpfx }}" + gateway_state: started + register: output +- name: Assert the resource instance did not change + ansible.builtin.assert: + that: + - not output.changed + - output.operational_state == 'Running' + +- name: Try to update instance of Application Gateway - no change + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway{{ rpfx }}" + sku: + name: standard_small + tier: standard + capacity: 2 + ssl_policy: + policy_type: predefined + policy_name: ssl_policy20150501 + authentication_certificates: + - name: cert1 + data: "{{ lookup('file', cert1_file) }}" + ssl_certificates: + - name: cert2 + password: your-password + data: "{{ lookup('file', cert2_file) }}" + gateway_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: app_gateway_ip_config + frontend_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: sample_gateway_frontend_ip_config + frontend_ports: + - port: 90 + name: ag_frontend_port + - port: 80 + name: http_frontend_port + backend_address_pools: + - backend_addresses: + - ip_address: 10.0.0.4 + name: test_backend_address_pool + probes: + - name: custom_probe + protocol: http + host: 10.0.0.4 + path: /healthz + interval: 30 + timeout: 30 + unhealthy_threshold: 3 + backend_http_settings_collection: + - port: 80 + protocol: http + cookie_based_affinity: enabled + probe: custom_probe + name: sample_appgateway_http_settings + http_listeners: + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: ag_frontend_port + protocol: https + ssl_certificate: cert2 + name: sample_http_listener + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: http_frontend_port + protocol: http + name: http_listener + request_routing_rules: + - rule_type: basic + backend_address_pool: test_backend_address_pool + backend_http_settings: sample_appgateway_http_settings + http_listener: sample_http_listener + name: rule1 + - rule_type: basic + http_listener: http_listener + redirect_configuration: redirect_site_to_https + name: http_redirect_rule + redirect_configurations: + - redirect_type: permanent + target_listener: sample_http_listener + include_path: true + include_query_string: true + name: redirect_site_to_https + register: output +- name: Assert the resource instance is not changed + ansible.builtin.assert: + that: + - not output.changed + +- name: Try to update instance of Application Gateway - single change + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway{{ rpfx }}" + sku: + name: standard_small + tier: standard + capacity: 2 + ssl_policy: + policy_type: predefined + policy_name: ssl_policy20150501 + authentication_certificates: + - name: cert1 + data: "{{ lookup('file', cert1_file) }}" + ssl_certificates: + - name: cert2 + password: your-password + data: "{{ lookup('file', cert2_file) }}" + gateway_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: app_gateway_ip_config + frontend_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: sample_gateway_frontend_ip_config + frontend_ports: + - port: 90 + name: ag_frontend_port + - port: 80 + name: http_frontend_port + backend_address_pools: + - backend_addresses: + - ip_address: 10.0.0.4 + name: test_backend_address_pool + probes: + - name: custom_probe + protocol: http + host: 10.0.0.4 + path: /healthz + interval: 30 + timeout: 30 + unhealthy_threshold: 3 + backend_http_settings_collection: + - port: 81 + protocol: http + cookie_based_affinity: enabled + probe: custom_probe + name: sample_appgateway_http_settings + http_listeners: + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: ag_frontend_port + protocol: https + ssl_certificate: cert2 + name: sample_http_listener + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: http_frontend_port + protocol: http + name: http_listener + request_routing_rules: + - rule_type: basic + backend_address_pool: test_backend_address_pool + backend_http_settings: sample_appgateway_http_settings + http_listener: sample_http_listener + name: rule1 + - rule_type: basic + http_listener: http_listener + redirect_configuration: redirect_site_to_https + name: http_redirect_rule + redirect_configurations: + - redirect_type: permanent + target_listener: sample_http_listener + include_path: true + include_query_string: true + name: redirect_site_to_https + register: output +- name: Assert the resource instance is updated + ansible.builtin.assert: + that: + - output.changed + +- name: Update SSL config for Application Gateway + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway{{ rpfx }}" + sku: + name: standard_small + tier: standard + capacity: 2 + ssl_policy: + policy_type: custom + cipher_suites: + - tls_ecdhe_rsa_with_aes_128_gcm_sha256 + - tls_ecdhe_ecdsa_with_aes_128_gcm_sha256 + - tls_ecdhe_ecdsa_with_aes_256_gcm_sha384 + min_protocol_version: tls_v1_2 + authentication_certificates: + - name: cert1 + data: "{{ lookup('file', cert1_file) }}" + ssl_certificates: + - name: cert2 + password: your-password + data: "{{ lookup('file', cert2_file) }}" + gateway_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: app_gateway_ip_config + frontend_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: sample_gateway_frontend_ip_config + frontend_ports: + - port: 90 + name: ag_frontend_port + - port: 80 + name: http_frontend_port + backend_address_pools: + - backend_addresses: + - ip_address: 10.0.0.4 + name: test_backend_address_pool + probes: + - name: custom_probe + protocol: http + host: 10.0.0.4 + path: /healthz + interval: 30 + timeout: 30 + unhealthy_threshold: 3 + backend_http_settings_collection: + - port: 81 + protocol: http + cookie_based_affinity: enabled + probe: custom_probe + name: sample_appgateway_http_settings + http_listeners: + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: ag_frontend_port + protocol: https + ssl_certificate: cert2 + name: sample_http_listener + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: http_frontend_port + protocol: http + name: http_listener + request_routing_rules: + - rule_type: basic + backend_address_pool: test_backend_address_pool + backend_http_settings: sample_appgateway_http_settings + http_listener: sample_http_listener + name: rule1 + - rule_type: basic + http_listener: http_listener + redirect_configuration: redirect_site_to_https + name: http_redirect_rule + redirect_configurations: + - redirect_type: permanent + target_listener: sample_http_listener + include_path: true + include_query_string: true + name: redirect_site_to_https + register: output +- name: Assert the resource instance is updated + ansible.builtin.assert: + that: + - output.changed + +- name: Load app gateway + azure_rm_appgateway_info: + name: "appgateway{{ rpfx }}" + resource_group: "{{ resource_group }}" + register: output +- name: Assert SSL config updated + ansible.builtin.assert: + that: + - output.gateways[0].ssl_policy.policy_type == 'custom' + +- name: Try to update SSL config for Application Gateway - no change + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway{{ rpfx }}" + sku: + name: standard_small + tier: standard + capacity: 2 + ssl_policy: + policy_type: custom + cipher_suites: + - tls_ecdhe_rsa_with_aes_128_gcm_sha256 + - tls_ecdhe_ecdsa_with_aes_128_gcm_sha256 + - tls_ecdhe_ecdsa_with_aes_256_gcm_sha384 + min_protocol_version: tls_v1_2 + authentication_certificates: + - name: cert1 + data: "{{ lookup('file', cert1_file) }}" + ssl_certificates: + - name: cert2 + password: your-password + data: "{{ lookup('file', cert2_file) }}" + gateway_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: app_gateway_ip_config + frontend_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: sample_gateway_frontend_ip_config + frontend_ports: + - port: 90 + name: ag_frontend_port + - port: 80 + name: http_frontend_port + backend_address_pools: + - backend_addresses: + - ip_address: 10.0.0.4 + name: test_backend_address_pool + probes: + - name: custom_probe + protocol: http + host: 10.0.0.4 + path: /healthz + interval: 30 + timeout: 30 + unhealthy_threshold: 3 + backend_http_settings_collection: + - port: 81 + protocol: http + cookie_based_affinity: enabled + probe: custom_probe + name: sample_appgateway_http_settings + http_listeners: + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: ag_frontend_port + protocol: https + ssl_certificate: cert2 + name: sample_http_listener + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: http_frontend_port + protocol: http + name: http_listener + request_routing_rules: + - rule_type: basic + backend_address_pool: test_backend_address_pool + backend_http_settings: sample_appgateway_http_settings + http_listener: sample_http_listener + name: rule1 + - rule_type: basic + http_listener: http_listener + redirect_configuration: redirect_site_to_https + name: http_redirect_rule + redirect_configurations: + - redirect_type: permanent + target_listener: sample_http_listener + include_path: true + include_query_string: true + name: redirect_site_to_https + register: output +- name: Assert the resource instance is not changed + ansible.builtin.assert: + that: + - not output.changed + +- name: Create instance of Application Gateway by looking up virtual network and subnet + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway-subnet-lookup{{ rpfx }}" + sku: + name: standard_small + tier: standard + capacity: 2 + ssl_policy: + policy_type: predefined + policy_name: ssl_policy20150501 + authentication_certificates: + - name: cert1 + data: "{{ lookup('file', cert1_file) }}" + ssl_certificates: + - name: cert2 + password: your-password + data: "{{ lookup('file', cert2_file) }}" + gateway_ip_configurations: + - subnet: + name: subnet{{ rpfx }} + virtual_network_name: vnet{{ rpfx }} + name: app_gateway_ip_config + frontend_ip_configurations: + - subnet: + name: subnet{{ rpfx }} + virtual_network_name: vnet{{ rpfx }} + name: sample_gateway_frontend_ip_config + frontend_ports: + - port: 90 + name: ag_frontend_port + - port: 80 + name: http_frontend_port + backend_address_pools: + - backend_addresses: + - ip_address: 10.0.0.4 + name: test_backend_address_pool + probes: + - name: custom_probe + protocol: http + host: 10.0.0.4 + path: /healthz + interval: 30 + timeout: 30 + unhealthy_threshold: 3 + backend_http_settings_collection: + - port: 80 + protocol: http + cookie_based_affinity: enabled + probe: custom_probe + name: sample_appgateway_http_settings + http_listeners: + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: ag_frontend_port + protocol: https + ssl_certificate: cert2 + name: sample_http_listener + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: http_frontend_port + protocol: http + name: http_listener + request_routing_rules: + - rule_type: basic + backend_address_pool: test_backend_address_pool + backend_http_settings: sample_appgateway_http_settings + http_listener: sample_http_listener + name: rule1 + - rule_type: basic + http_listener: http_listener + redirect_configuration: redirect_site_to_https + name: http_redirect_rule + redirect_configurations: + - redirect_type: permanent + target_listener: sample_http_listener + include_path: true + include_query_string: true + name: redirect_site_to_https + register: output +- name: Assert the resource instance is well created + ansible.builtin.assert: + that: + - output.changed - name: Load app gateways azure_rm_appgateway_info: register: appgw_output -- name: Assert there are no gateways +- name: Assert there are the correct number of gateways + ansible.builtin.assert: + that: + - appgw_output.gateways | community.general.json_query(query) | length == 2 + +- name: Load app gateway by name + azure_rm_appgateway_info: + name: "appgateway-subnet-lookup{{ rpfx }}" + resource_group: "{{ resource_group }}" + register: appgw_output +- name: Assert there are the correct number of gateways + ansible.builtin.assert: + that: + - appgw_output.gateways | community.general.json_query(query) | length == 1 + - (appgw_output.gateways | community.general.json_query(query))[0].name == 'appgateway-subnet-lookup{{ rpfx }}' + - (appgw_output.gateways | community.general.json_query(query))[0].provisioning_state == 'Succeeded' + - (appgw_output.gateways | community.general.json_query(query))[0].operational_state == 'Running' + +- name: Create instance of Application Gateway with probe using hostname from backend http settings + azure_rm_appgateway: + resource_group: "{{ resource_group_secondary }}" + name: "appgateway-probe-{{ rpfx }}" + location: "{{ vnet_output.state.location }}" + sku: + name: standard_small + tier: standard + capacity: 2 + ssl_policy: + policy_type: predefined + policy_name: ssl_policy20150501 + authentication_certificates: + - name: cert1 + data: "{{ lookup('file', cert1_file) }}" + ssl_certificates: + - name: cert2 + password: your-password + data: "{{ lookup('file', cert2_file) }}" + gateway_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: app_gateway_ip_config + frontend_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: sample_gateway_frontend_ip_config + frontend_ports: + - port: 90 + name: ag_frontend_port + - port: 80 + name: http_frontend_port + backend_address_pools: + - backend_addresses: + - ip_address: 10.0.0.4 + name: test_backend_address_pool + probes: + - name: custom_probe + protocol: http + path: /healthz + interval: 30 + timeout: 30 + unhealthy_threshold: 3 + pick_host_name_from_backend_http_settings: true + backend_http_settings_collection: + - port: 80 + protocol: http + cookie_based_affinity: enabled + probe: custom_probe + name: sample_appgateway_http_settings + pick_host_name_from_backend_address: true + http_listeners: + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: ag_frontend_port + protocol: https + ssl_certificate: cert2 + name: sample_http_listener + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: http_frontend_port + protocol: http + name: http_listener + request_routing_rules: + - rule_type: basic + backend_address_pool: test_backend_address_pool + backend_http_settings: sample_appgateway_http_settings + http_listener: sample_http_listener + name: rule1 + - rule_type: basic + http_listener: http_listener + redirect_configuration: redirect_site_to_https + name: http_redirect_rule + redirect_configurations: + - redirect_type: permanent + target_listener: sample_http_listener + include_path: true + include_query_string: true + name: redirect_site_to_https + register: output +- name: Assert the resource instance is well created + ansible.builtin.assert: + that: + - output.changed + +- name: Test no update instance of Application Gateway with probe using hostname from backend http settings + azure_rm_appgateway: + resource_group: "{{ resource_group_secondary }}" + name: "appgateway-probe-{{ rpfx }}" + location: "{{ vnet_output.state.location }}" + sku: + name: standard_small + tier: standard + capacity: 2 + ssl_policy: + policy_type: predefined + policy_name: ssl_policy20150501 + authentication_certificates: + - name: cert1 + data: "{{ lookup('file', cert1_file) }}" + ssl_certificates: + - name: cert2 + password: your-password + data: "{{ lookup('file', cert2_file) }}" + gateway_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: app_gateway_ip_config + frontend_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: sample_gateway_frontend_ip_config + frontend_ports: + - port: 90 + name: ag_frontend_port + - port: 80 + name: http_frontend_port + backend_address_pools: + - backend_addresses: + - ip_address: 10.0.0.4 + name: test_backend_address_pool + probes: + - name: custom_probe + protocol: http + path: /healthz + interval: 30 + timeout: 30 + unhealthy_threshold: 3 + pick_host_name_from_backend_http_settings: true + backend_http_settings_collection: + - port: 80 + protocol: http + cookie_based_affinity: enabled + probe: custom_probe + name: sample_appgateway_http_settings + pick_host_name_from_backend_address: true + http_listeners: + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: ag_frontend_port + protocol: https + ssl_certificate: cert2 + name: sample_http_listener + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: http_frontend_port + protocol: http + name: http_listener + request_routing_rules: + - rule_type: basic + backend_address_pool: test_backend_address_pool + backend_http_settings: sample_appgateway_http_settings + http_listener: sample_http_listener + name: rule1 + - rule_type: basic + http_listener: http_listener + redirect_configuration: redirect_site_to_https + name: http_redirect_rule + redirect_configurations: + - redirect_type: permanent + target_listener: sample_http_listener + include_path: true + include_query_string: true + name: redirect_site_to_https + register: output +- name: Assert the resource instance is not changed + ansible.builtin.assert: + that: + - not output.changed + +- name: Load app gateway by resource group + azure_rm_appgateway_info: + resource_group: "{{ resource_group_secondary }}" + register: appgw_output +- name: Assert there are the correct number of gateways and they are the right ones + ansible.builtin.assert: + that: + - appgw_output.gateways | community.general.json_query(query) | length == 1 + - (appgw_output.gateways | community.general.json_query(query))[0].name == 'appgateway-probe-{{ rpfx }}' + +- name: Load app gateway not found in resource group + azure_rm_appgateway_info: + name: "appgateway{{ rpfx }}" + resource_group: "{{ resource_group_secondary }}" + register: appgw_output +- name: Assert there are no results + ansible.builtin.assert: + that: + - appgw_output.gateways | community.general.json_query(query) | length == 0 + +- name: Create instance of Application Gateway with path based rules + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway-path-rules{{ rpfx }}" + sku: + name: standard_small + tier: standard + capacity: 2 + ssl_policy: + policy_type: predefined + policy_name: ssl_policy20150501 + authentication_certificates: + - name: cert1 + data: "{{ lookup('file', cert1_file) }}" + ssl_certificates: + - name: cert2 + password: your-password + data: "{{ lookup('file', cert2_file) }}" + gateway_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: app_gateway_ip_config + frontend_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: sample_gateway_frontend_ip_config + frontend_ports: + - port: 90 + name: ag_frontend_port + - port: 80 + name: http_frontend_port + backend_address_pools: + - backend_addresses: + - ip_address: 10.0.0.4 + name: test_backend_address_pool + probes: + - name: custom_probe + protocol: http + host: 10.0.0.4 + path: /healthz + interval: 30 + timeout: 30 + unhealthy_threshold: 3 + backend_http_settings_collection: + - port: 80 + protocol: http + cookie_based_affinity: enabled + probe: custom_probe + name: sample_appgateway_http_settings + http_listeners: + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: ag_frontend_port + protocol: https + ssl_certificate: cert2 + name: sample_http_listener + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: http_frontend_port + protocol: http + name: http_listener + request_routing_rules: + - rule_type: path_based_routing + http_listener: sample_http_listener + name: rule1 + url_path_map: path_mappings + - rule_type: basic + http_listener: http_listener + redirect_configuration: redirect_site_to_https + name: http_redirect_rule + url_path_maps: + - name: path_mappings + default_backend_address_pool: test_backend_address_pool + default_backend_http_settings: sample_appgateway_http_settings + path_rules: + - name: path_rules + backend_address_pool: test_backend_address_pool + backend_http_settings: sample_appgateway_http_settings + paths: + - "/abc" + - "/123/*" + redirect_configurations: + - redirect_type: permanent + target_listener: sample_http_listener + include_path: true + include_query_string: true + name: redirect_site_to_https + register: output +- name: Assert the resource instance is well created ansible.builtin.assert: that: - - appgw_output.gateways | community.general.json_query(query) | length == 0 - -- name: Create a virtual network - azure_rm_virtualnetwork: - name: vnet{{ rpfx }} - resource_group: "{{ resource_group }}" - address_prefixes_cidr: - - 10.1.0.0/16 - - 172.100.0.0/16 - dns_servers: - - 127.0.0.1 - - 127.0.0.2 - register: vnet_output -- name: Create a subnet - azure_rm_subnet: - name: subnet{{ rpfx }} - virtual_network_name: vnet{{ rpfx }} - resource_group: "{{ resource_group }}" - address_prefix_cidr: 10.1.0.0/24 - register: subnet_output + - output.changed -- name: Configure public IP for v2 gateway - azure_rm_publicipaddress: - name: "appgateway-v2-{{ rpfx }}-pip" +- name: Try to update instance of Application Gateway with path based rules - no change + azure_rm_appgateway: resource_group: "{{ resource_group }}" - sku: "standard" - allocation_method: "static" + name: "appgateway-path-rules{{ rpfx }}" + sku: + name: standard_small + tier: standard + capacity: 2 + ssl_policy: + policy_type: predefined + policy_name: ssl_policy20150501 + authentication_certificates: + - name: cert1 + data: "{{ lookup('file', cert1_file) }}" + ssl_certificates: + - name: cert2 + password: your-password + data: "{{ lookup('file', cert2_file) }}" + gateway_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: app_gateway_ip_config + frontend_ip_configurations: + - subnet: + id: "{{ subnet_output.state.id }}" + name: sample_gateway_frontend_ip_config + frontend_ports: + - port: 90 + name: ag_frontend_port + - port: 80 + name: http_frontend_port + backend_address_pools: + - backend_addresses: + - ip_address: 10.0.0.4 + name: test_backend_address_pool + probes: + - name: custom_probe + protocol: http + host: 10.0.0.4 + path: /healthz + interval: 30 + timeout: 30 + unhealthy_threshold: 3 + backend_http_settings_collection: + - port: 80 + protocol: http + cookie_based_affinity: enabled + probe: custom_probe + name: sample_appgateway_http_settings + http_listeners: + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: ag_frontend_port + protocol: https + ssl_certificate: cert2 + name: sample_http_listener + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: http_frontend_port + protocol: http + name: http_listener + request_routing_rules: + - rule_type: path_based_routing + http_listener: sample_http_listener + name: rule1 + url_path_map: path_mappings + - rule_type: basic + http_listener: http_listener + redirect_configuration: redirect_site_to_https + name: http_redirect_rule + url_path_maps: + - name: path_mappings + default_backend_address_pool: test_backend_address_pool + default_backend_http_settings: sample_appgateway_http_settings + path_rules: + - name: path_rules + backend_address_pool: test_backend_address_pool + backend_http_settings: sample_appgateway_http_settings + paths: + - "/abc" + - "/123/*" + redirect_configurations: + - redirect_type: permanent + target_listener: sample_http_listener + include_path: true + include_query_string: true + name: redirect_site_to_https + register: output +- name: Assert the resource instance is not changed + ansible.builtin.assert: + that: + - not output.changed -- name: Try to create v2 instance of Application Gateway with rewrite rules +- name: Create instance of Application Gateway with complex routing and redirect rules azure_rm_appgateway: resource_group: "{{ resource_group }}" - name: "appgateway-v2-{{ rpfx }}" + name: "appgateway-complex{{ rpfx }}" sku: - name: standard_v2 - tier: standard_v2 + name: standard_small + tier: standard capacity: 2 ssl_policy: policy_type: "predefined" @@ -89,8 +1120,9 @@ id: "{{ subnet_output.state.id }}" name: app_gateway_ip_config frontend_ip_configurations: - - name: "public-inbound-ip" - public_ip_address: "appgateway-v2-{{ rpfx }}-pip" + - subnet: + id: "{{ subnet_output.state.id }}" + name: sample_gateway_frontend_ip_config frontend_ports: - name: "inbound-http" port: 80 @@ -109,28 +1141,28 @@ protocol: https pick_host_name_from_backend_address: true probe: "http-probe1" - cookie_based_affinity: "disabled" + cookie_based_affinity: "Disabled" - name: "http-profile2" port: 8080 protocol: http pick_host_name_from_backend_address: true probe: "http-probe2" - cookie_based_affinity: "disabled" + cookie_based_affinity: "Disabled" http_listeners: - name: "inbound-http" protocol: "http" - frontend_ip_configuration: "public-inbound-ip" + frontend_ip_configuration: "sample_gateway_frontend_ip_config" frontend_port: "inbound-http" - name: "inbound-traffic1" protocol: "https" - frontend_ip_configuration: "public-inbound-ip" + frontend_ip_configuration: "sample_gateway_frontend_ip_config" frontend_port: "inbound-https" host_name: "traffic1.example.com" require_server_name_indication: true ssl_certificate: "cert2" - name: "inbound-traffic2" protocol: "https" - frontend_ip_configuration: "public-inbound-ip" + frontend_ip_configuration: "sample_gateway_frontend_ip_config" frontend_port: "inbound-https" host_name: "traffic2.example.com" require_server_name_indication: true @@ -138,7 +1170,6 @@ url_path_maps: - name: "path_mappings" default_redirect_configuration: "redirect-traffic1" - default_rewrite_rule_set: "configure-headers" path_rules: - name: "path_rules" backend_address_pool: "test_backend_address_pool1" @@ -152,7 +1183,6 @@ http_listener: "inbound-traffic1" backend_address_pool: "test_backend_address_pool2" backend_http_settings: "http-profile1" - rewrite_rule_set: "configure-headers" - name: "app-routing2" rule_type: "path_based_routing" http_listener: "inbound-traffic2" @@ -161,33 +1191,6 @@ rule_type: "basic" http_listener: "inbound-http" redirect_configuration: "redirect-http" - rewrite_rule_sets: - - name: "configure-headers" - rewrite_rules: - - name: "add-security-response-header" - rule_sequence: 1 - action_set: - response_header_configurations: - - header_name: "Strict-Transport-Security" - header_value: "max-age=31536000" - - name: "remove-backend-response-headers" - rule_sequence: 2 - action_set: - response_header_configurations: - - header_name: "Server" - - header_name: "X-Powered-By" - - name: "set-custom-header-condition" - rule_sequence: 3 - conditions: - - variable: "var_client_ip" - pattern: "1.1.1.1" - - variable: "http_req_Authorization" - pattern: "12345" - ignore_case: false - action_set: - request_header_configurations: - - header_name: "Foo" - header_value: "Bar" probes: - name: "http-probe1" interval: 30 @@ -224,13 +1227,13 @@ that: - output.changed -- name: Try to create v2 instance of Application Gateway with rewrite rules - no update +- name: Try to update instance of Application Gateway with complex routing and redirect rules - no change azure_rm_appgateway: resource_group: "{{ resource_group }}" - name: "appgateway-v2-{{ rpfx }}" + name: "appgateway-complex{{ rpfx }}" sku: - name: standard_v2 - tier: standard_v2 + name: standard_small + tier: standard capacity: 2 ssl_policy: policy_type: "predefined" @@ -244,8 +1247,9 @@ id: "{{ subnet_output.state.id }}" name: app_gateway_ip_config frontend_ip_configurations: - - name: "public-inbound-ip" - public_ip_address: "appgateway-v2-{{ rpfx }}-pip" + - subnet: + id: "{{ subnet_output.state.id }}" + name: sample_gateway_frontend_ip_config frontend_ports: - name: "inbound-http" port: 80 @@ -264,28 +1268,28 @@ protocol: https pick_host_name_from_backend_address: true probe: "http-probe1" - cookie_based_affinity: "disabled" + cookie_based_affinity: "Disabled" - name: "http-profile2" port: 8080 protocol: http pick_host_name_from_backend_address: true probe: "http-probe2" - cookie_based_affinity: "disabled" + cookie_based_affinity: "Disabled" http_listeners: - name: "inbound-http" protocol: "http" - frontend_ip_configuration: "public-inbound-ip" + frontend_ip_configuration: "sample_gateway_frontend_ip_config" frontend_port: "inbound-http" - name: "inbound-traffic1" protocol: "https" - frontend_ip_configuration: "public-inbound-ip" + frontend_ip_configuration: "sample_gateway_frontend_ip_config" frontend_port: "inbound-https" host_name: "traffic1.example.com" require_server_name_indication: true ssl_certificate: "cert2" - name: "inbound-traffic2" protocol: "https" - frontend_ip_configuration: "public-inbound-ip" + frontend_ip_configuration: "sample_gateway_frontend_ip_config" frontend_port: "inbound-https" host_name: "traffic2.example.com" require_server_name_indication: true @@ -293,7 +1297,6 @@ url_path_maps: - name: "path_mappings" default_redirect_configuration: "redirect-traffic1" - default_rewrite_rule_set: "configure-headers" path_rules: - name: "path_rules" backend_address_pool: "test_backend_address_pool1" @@ -307,7 +1310,6 @@ http_listener: "inbound-traffic1" backend_address_pool: "test_backend_address_pool2" backend_http_settings: "http-profile1" - rewrite_rule_set: "configure-headers" - name: "app-routing2" rule_type: "path_based_routing" http_listener: "inbound-traffic2" @@ -316,33 +1318,6 @@ rule_type: "basic" http_listener: "inbound-http" redirect_configuration: "redirect-http" - rewrite_rule_sets: - - name: "configure-headers" - rewrite_rules: - - name: "add-security-response-header" - rule_sequence: 1 - action_set: - response_header_configurations: - - header_name: "Strict-Transport-Security" - header_value: "max-age=31536000" - - name: "remove-backend-response-headers" - rule_sequence: 2 - action_set: - response_header_configurations: - - header_name: "Server" - - header_name: "X-Powered-By" - - name: "set-custom-header-condition" - rule_sequence: 3 - conditions: - - variable: "var_client_ip" - pattern: "1.1.1.1" - - variable: "http_req_Authorization" - pattern: "12345" - ignore_case: false - action_set: - request_header_configurations: - - header_name: "Foo" - header_value: "Bar" probes: - name: "http-probe1" interval: 30 @@ -374,12 +1349,19 @@ url_path_maps: - "path_mappings" register: output -- name: Assert the resource instance is not updated +- name: Assert the resource instance is not changed ansible.builtin.assert: that: - not output.changed -- name: Try to create v2 instance of Application Gateway with rewrite rules - update rewrite rule +- name: Configure public IP for v2 gateway + azure_rm_publicipaddress: + name: "appgateway-v2-{{ rpfx }}-pip" + resource_group: "{{ resource_group }}" + sku: "standard" + allocation_method: "static" + +- name: Try to create v2 instance of Application Gateway with rewrite rules azure_rm_appgateway: resource_group: "{{ resource_group }}" name: "appgateway-v2-{{ rpfx }}" @@ -419,13 +1401,13 @@ protocol: https pick_host_name_from_backend_address: true probe: "http-probe1" - cookie_based_affinity: "disabled" + cookie_based_affinity: "Disabled" - name: "http-profile2" port: 8080 protocol: http pick_host_name_from_backend_address: true probe: "http-probe2" - cookie_based_affinity: "disabled" + cookie_based_affinity: "Disabled" http_listeners: - name: "inbound-http" protocol: "http" @@ -497,10 +1479,7 @@ action_set: request_header_configurations: - header_name: "Foo" - header_value: "BarUpdated" - response_header_configurations: - - header_name: "FooResponse" - header_value: "BarResponse" + header_value: "Bar" probes: - name: "http-probe1" interval: 30 @@ -532,12 +1511,12 @@ url_path_maps: - "path_mappings" register: output -- name: Assert the resource instance is updated +- name: Assert the resource instance is well created ansible.builtin.assert: that: - output.changed -- name: Try to create v2 instance of Application Gateway with UserAssigned identity +- name: Try to create v2 instance of Application Gateway with rewrite rules - no update azure_rm_appgateway: resource_group: "{{ resource_group }}" name: "appgateway-v2-{{ rpfx }}" @@ -577,13 +1556,13 @@ protocol: https pick_host_name_from_backend_address: true probe: "http-probe1" - cookie_based_affinity: "disabled" + cookie_based_affinity: "Disabled" - name: "http-profile2" port: 8080 protocol: http pick_host_name_from_backend_address: true probe: "http-probe2" - cookie_based_affinity: "disabled" + cookie_based_affinity: "Disabled" http_listeners: - name: "inbound-http" protocol: "http" @@ -655,10 +1634,7 @@ action_set: request_header_configurations: - header_name: "Foo" - header_value: "BarUpdated" - response_header_configurations: - - header_name: "FooResponse" - header_value: "BarResponse" + header_value: "Bar" probes: - name: "http-probe1" interval: 30 @@ -689,18 +1665,13 @@ include_query_string: true url_path_maps: - "path_mappings" - identity: - type: UserAssigned - user_assigned_identities: - id: - - "{{ user_identity_1 }}" register: output -- name: Assert the resource instance is updated +- name: Assert the resource instance is not updated ansible.builtin.assert: that: - - output.changed + - not output.changed -- name: Try to create v2 instance of Application Gateway with no Update +- name: Try to create v2 instance of Application Gateway with rewrite rules - update rewrite rule azure_rm_appgateway: resource_group: "{{ resource_group }}" name: "appgateway-v2-{{ rpfx }}" @@ -740,13 +1711,13 @@ protocol: https pick_host_name_from_backend_address: true probe: "http-probe1" - cookie_based_affinity: "disabled" + cookie_based_affinity: "Disabled" - name: "http-profile2" port: 8080 protocol: http pick_host_name_from_backend_address: true probe: "http-probe2" - cookie_based_affinity: "disabled" + cookie_based_affinity: "Disabled" http_listeners: - name: "inbound-http" protocol: "http" @@ -852,16 +1823,11 @@ include_query_string: true url_path_maps: - "path_mappings" - identity: - type: UserAssigned - user_assigned_identities: - id: - - "{{ user_identity_1 }}" register: output - name: Assert the resource instance is updated ansible.builtin.assert: that: - - not output.changed + - output.changed - name: Try to create v2 instance of Application Gateway with autoscale configuration and trusted root certificates azure_rm_appgateway: @@ -909,7 +1875,7 @@ protocol: https pick_host_name_from_backend_address: true probe: "http-probe1" - cookie_based_affinity: "disabled" + cookie_based_affinity: "Disabled" connection_draining: drain_timeout_in_sec: 60 enabled: true @@ -920,7 +1886,7 @@ protocol: http pick_host_name_from_backend_address: true probe: "http-probe2" - cookie_based_affinity: "disabled" + cookie_based_affinity: "Disabled" http_listeners: - name: "inbound-http" protocol: "http" @@ -1077,7 +2043,7 @@ protocol: https pick_host_name_from_backend_address: true probe: "http-probe1" - cookie_based_affinity: "disabled" + cookie_based_affinity: "Disabled" connection_draining: drain_timeout_in_sec: 60 enabled: true @@ -1088,7 +2054,7 @@ protocol: http pick_host_name_from_backend_address: true probe: "http-probe2" - cookie_based_affinity: "disabled" + cookie_based_affinity: "Disabled" http_listeners: - name: "inbound-http" protocol: "http" @@ -1245,13 +2211,13 @@ protocol: https pick_host_name_from_backend_address: true probe: "http-probe1" - cookie_based_affinity: "disabled" + cookie_based_affinity: "Disabled" - name: "http-profile2" port: 8080 protocol: http pick_host_name_from_backend_address: true probe: "http-probe2" - cookie_based_affinity: "disabled" + cookie_based_affinity: "Disabled" http_listeners: - name: "inbound-http" protocol: "http" @@ -1409,13 +2375,13 @@ protocol: https pick_host_name_from_backend_address: true probe: "http-probe1" - cookie_based_affinity: "disabled" + cookie_based_affinity: "Disabled" - name: "http-profile2" port: 8080 protocol: http pick_host_name_from_backend_address: true probe: "http-probe2" - cookie_based_affinity: "disabled" + cookie_based_affinity: "Disabled" http_listeners: - name: "inbound-http" protocol: "http" @@ -1533,6 +2499,73 @@ that: - not output.changed +- name: Delete instance of Application Gateway -- check mode + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway{{ rpfx }}" + state: absent + check_mode: true + register: output +- name: Assert the state has changed + ansible.builtin.assert: + that: + - output.changed + +- name: Delete instance of Application Gateway + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway{{ rpfx }}" + state: absent + register: output +- name: Assert the state has changed + ansible.builtin.assert: + that: + - output.changed + +- name: Delete unexisting instance of Application Gateway + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway{{ rpfx }}" + state: absent + register: output +- name: Assert the state has changed + ansible.builtin.assert: + that: + - output.changed == false + +- name: Delete path-based rules instance of Application Gateway + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway-path-rules{{ rpfx }}" + state: absent + register: output +- name: Assert the state has changed + ansible.builtin.assert: + that: + - output.changed + +- name: Delete custom probe instance of Application Gateway + azure_rm_appgateway: + resource_group: "{{ resource_group_secondary }}" + name: "appgateway-probe-{{ rpfx }}" + state: absent + register: output +- name: Assert the state has changed + ansible.builtin.assert: + that: + - output.changed + +- name: Delete subnet-lookup instance of Application Gateway + azure_rm_appgateway: + resource_group: "{{ resource_group }}" + name: "appgateway-subnet-lookup{{ rpfx }}" + state: absent + register: output +- name: Assert the state has changed + ansible.builtin.assert: + that: + - output.changed + - name: Delete v2 instance of Application Gateway azure_rm_appgateway: resource_group: "{{ resource_group }}" @@ -1577,20 +2610,19 @@ that: - output.changed -- name: Delete virtual network - azure_rm_virtualnetwork: - name: vnet{{ rpfx }} +- name: Delete complex instance of Application Gateway + azure_rm_appgateway: resource_group: "{{ resource_group }}" + name: "appgateway-complex{{ rpfx }}" state: absent + register: output +- name: Assert the state has changed + ansible.builtin.assert: + that: + - output.changed -- name: Destroy User Managed Identities - azure_rm_resource: +- name: Delete virtual network + azure_rm_virtualnetwork: + name: vnet{{ rpfx }} resource_group: "{{ resource_group }}" - provider: ManagedIdentity - resource_type: userAssignedIdentities - resource_name: "{{ item }}" - api_version: "2023-01-31" state: absent - loop: - - "ansible-test-appgw-identity" - - "ansible-test-appgw-identity-2" diff --git a/tests/integration/targets/azure_rm_batchaccount/tasks/main.yml b/tests/integration/targets/azure_rm_batchaccount/tasks/main.yml index 20a56d42c..e56a572a7 100644 --- a/tests/integration/targets/azure_rm_batchaccount/tasks/main.yml +++ b/tests/integration/targets/azure_rm_batchaccount/tasks/main.yml @@ -23,38 +23,6 @@ location: eastus account_type: Standard_LRS -- name: Gather Resource Group info - azure.azcollection.azure_rm_resourcegroup_info: - name: "{{ resource_group }}" - register: __rg_info - -- name: Set location based on resource group - ansible.builtin.set_fact: - location: "{{ __rg_info.resourcegroups.0.location }}" - -- name: Create User Managed Identities - azure_rm_resource: - resource_group: "{{ resource_group }}" - provider: ManagedIdentity - resource_type: userAssignedIdentities - resource_name: "{{ item }}" - api_version: "2023-01-31" - body: - location: "{{ location }}" - state: present - loop: - - "ansible-test-batchaccount-identity" - - "ansible-test-batchaccount-identity-2" - -- name: Set identities base path - ansible.builtin.set_fact: - identity_base_path: "/subscriptions/{{ azure_subscription_id }}/resourcegroups/{{ resource_group }}/providers/Microsoft.ManagedIdentity" - -- name: Set identities IDs to test. Identities ansible-test-batchaccount-identity and ansible-test-batchaccount-identity-2 have to be created previously - ansible.builtin.set_fact: - user_identity_1: "{{ identity_base_path }}/userAssignedIdentities/ansible-test-batchaccount-identity" - user_identity_2: "{{ identity_base_path }}/userAssignedIdentities/ansible-test-batchaccount-identity-2" - - name: Create Batch Account azure_rm_batchaccount: resource_group: "{{ resource_group }}" @@ -66,18 +34,12 @@ tags: key1: value1 key2: value2 - identity: - type: UserAssigned - user_assigned_identity: "{{ user_identity_1 }}" register: output - name: Assert the resource was created ansible.builtin.assert: that: - output.changed - - output.new.identity.type == "UserAssigned" - - output.new.identity.user_assigned_identities | length == 1 - - output.new.identity.user_assigned_identities['{{ user_identity_1 }}'] is defined - name: Create Batch Account -- idempotent azure_rm_batchaccount: @@ -90,42 +52,12 @@ tags: key1: value1 key2: value2 - identity: - type: UserAssigned - user_assigned_identity: "{{ user_identity_1 }}" register: output -- name: Assert the resource wasn't changed +- name: Assert the resource was created ansible.builtin.assert: that: - not output.changed - - output.new.identity.type == "UserAssigned" - - output.new.identity.user_assigned_identities | length == 1 - - output.new.identity.user_assigned_identities['{{ user_identity_1 }}'] is defined - -- name: Update user assigned identity - azure_rm_batchaccount: - resource_group: "{{ resource_group }}" - name: "{{ batch_account_name }}" - location: eastus - auto_storage_account: - name: "{{ storage_account_name }}" - pool_allocation_mode: batch_service - tags: - key1: value1 - key2: value2 - identity: - type: UserAssigned - user_assigned_identity: "{{ user_identity_2 }}" - register: output - -- name: Assert the resource was changed - ansible.builtin.assert: - that: - - output.changed - - output.new.identity.type == "UserAssigned" - - output.new.identity.user_assigned_identities | length == 1 - - output.new.identity.user_assigned_identities['{{ user_identity_2 }}'] is defined - name: Get Batch Account facts azure_rm_batchaccount_info: @@ -138,31 +70,6 @@ that: - output.batch_account | length == 1 - output.batch_account[0].tags | length == 2 - - output.batch_account[0].identity.type == "UserAssigned" - - output.batch_account[0].identity.user_assigned_identities | length == 1 - - output.batch_account[0].identity.user_assigned_identities['{{ user_identity_2 }}'] is defined - -- name: Update identity type to SystemAssigned - azure_rm_batchaccount: - resource_group: "{{ resource_group }}" - name: "{{ batch_account_name }}" - location: eastus - auto_storage_account: - name: "{{ storage_account_name }}" - pool_allocation_mode: batch_service - tags: - key1: value1 - key2: value2 - identity: - type: SystemAssigned - register: output - -- name: Assert the resource was changed - ansible.builtin.assert: - that: - - output.changed - - output.new.identity.type == "SystemAssigned" - - output.new.identity.user_assigned_identities is not defined - name: Delete Batch Account azure_rm_batchaccount: @@ -181,15 +88,3 @@ resource_group: "{{ resource_group }}" name: "{{ storage_account_name }}" state: absent - -- name: Destroy User Managed Identities - azure_rm_resource: - resource_group: "{{ resource_group }}" - provider: ManagedIdentity - resource_type: userAssignedIdentities - resource_name: "{{ item }}" - api_version: "2023-01-31" - state: absent - loop: - - "ansible-test-batchaccount-identity" - - "ansible-test-batchaccount-identity-2" diff --git a/tests/integration/targets/azure_rm_capacityreservationgroup/aliases b/tests/integration/targets/azure_rm_capacityreservationgroup/aliases deleted file mode 100644 index aa77c071a..000000000 --- a/tests/integration/targets/azure_rm_capacityreservationgroup/aliases +++ /dev/null @@ -1,3 +0,0 @@ -cloud/azure -shippable/azure/group2 -destructive diff --git a/tests/integration/targets/azure_rm_capacityreservationgroup/meta/main.yml b/tests/integration/targets/azure_rm_capacityreservationgroup/meta/main.yml deleted file mode 100644 index 95e1952f9..000000000 --- a/tests/integration/targets/azure_rm_capacityreservationgroup/meta/main.yml +++ /dev/null @@ -1,2 +0,0 @@ -dependencies: - - setup_azure diff --git a/tests/integration/targets/azure_rm_capacityreservationgroup/tasks/main.yml b/tests/integration/targets/azure_rm_capacityreservationgroup/tasks/main.yml deleted file mode 100644 index bc22311a4..000000000 --- a/tests/integration/targets/azure_rm_capacityreservationgroup/tasks/main.yml +++ /dev/null @@ -1,85 +0,0 @@ -- name: Prepare random number - ansible.builtin.set_fact: - random_postfix: "{{ resource_group | hash('md5') | truncate(10, True, '') }}" - -- name: Create a new capacity reservation group(Checkmode test) - azure_rm_capacityreservationgroup: - resource_group: "{{ resource_group }}" - name: "{{ random_postfix }}" - zones: - - 1 - - 2 - tags: - key1: value1 - check_mode: true - -- name: Create a new capacity reservation group - azure_rm_capacityreservationgroup: - resource_group: "{{ resource_group }}" - name: "{{ random_postfix }}" - zones: - - 1 - - 2 - tags: - key1: value1 - register: output - -- name: Assert the capacity reservation group created - ansible.builtin.assert: - that: - - output.changed - -- name: Update the capacity reservation group's tag - azure_rm_capacityreservationgroup: - resource_group: "{{ resource_group }}" - name: "{{ random_postfix }}" - zones: - - 1 - - 2 - tags: - key2: value2 - register: output - -- name: Assert the capacity reservation group updated - ansible.builtin.assert: - that: - - output.changed - -- name: Recreate the capacity reservation group(idempotent test) - azure_rm_capacityreservationgroup: - resource_group: "{{ resource_group }}" - name: "{{ random_postfix }}" - zones: - - 1 - - 2 - tags: - key2: value2 - register: output - -- name: Assert the capacity reservation group no change - ansible.builtin.assert: - that: - - not output.changed - -- name: Get capacity reservation group by name - azure_rm_capacityreservationgroup_info: - resource_group: "{{ resource_group }}" - name: "{{ random_postfix }}" - register: output - -- name: Assert the capacity reservation group no change - ansible.builtin.assert: - that: - - output.capacity_reservation_groups[0].tags | length == 2 - -- name: Delete the capacity reservation group - azure_rm_capacityreservationgroup: - resource_group: "{{ resource_group }}" - name: "{{ random_postfix }}" - state: absent - register: output - -- name: Assert the capacity reservation group deleted - ansible.builtin.assert: - that: - - output.changed diff --git a/tests/integration/targets/azure_rm_containerinstance/tasks/main.yml b/tests/integration/targets/azure_rm_containerinstance/tasks/main.yml index 535474e1b..d8bd5f36e 100644 --- a/tests/integration/targets/azure_rm_containerinstance/tasks/main.yml +++ b/tests/integration/targets/azure_rm_containerinstance/tasks/main.yml @@ -2,34 +2,6 @@ ansible.builtin.set_fact: rpfx: "{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}" -- name: Gather Resource Group info - azure.azcollection.azure_rm_resourcegroup_info: - name: "{{ resource_group }}" - register: __rg_info - -- name: Set Azure Region based on resource group location - ansible.builtin.set_fact: - location: "{{ __rg_info.resourcegroups.0.location }}" - -- name: Create User Managed Identities - azure_rm_resource: - resource_group: "{{ resource_group }}" - provider: ManagedIdentity - resource_type: userAssignedIdentities - resource_name: "{{ item }}" - api_version: "2023-01-31" - body: - location: "{{ location }}" - state: present - loop: - - "ansible-test-aci-identity" - - "ansible-test-aci-identity-2" - -- name: Set identities IDs to test. Identities ansible-test-aci-identity and ansible-test-aci-identity-2 have to be created previously - ansible.builtin.set_fact: - user_identity_1: "/subscriptions/{{ azure_subscription_id }}/resourcegroups/{{ resource_group }}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/ansible-test-aci-identity" - user_identity_2: "/subscriptions/{{ azure_subscription_id }}/resourcegroups/{{ resource_group }}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/ansible-test-aci-identity-2" - - name: Create sample container instance azure_rm_containerinstance: resource_group: "{{ resource_group }}" @@ -97,15 +69,9 @@ ports: - 80 - 81 - identity: - type: SystemAssigned force_update: true register: output -- name: Print the created results - ansible.builtin.debug: - var: output - - name: Assert the container instance is well created ansible.builtin.assert: that: @@ -229,72 +195,6 @@ - output.containerinstances[1]['ports'] != None - output.containerinstances[1]['containers'] != None -- name: Create sample container instance -- User Identity - azure_rm_containerinstance: - resource_group: "{{ resource_group }}" - name: "aci{{ rpfx }}fourth" - os_type: linux - ip_address: public - location: eastus - ports: - - 80 - containers: - - name: mycontainer1 - image: httpd - memory: 1.5 - ports: - - 80 - - 81 - identity: - type: UserAssigned - user_assigned_identities: - id: - - "{{ user_identity_1 }}" - - "{{ user_identity_2 }}" - register: output - -- name: Gather facts for single Container Instance - azure_rm_containerinstance_info: - resource_group: "{{ resource_group }}" - name: "aci{{ rpfx }}fourth" - register: output - -- name: Print the container instance facts - ansible.builtin.debug: - var: output - -- name: Assert that user identities are used - ansible.builtin.assert: - that: - - output.changed == False - - user_identity_1 in output.containerinstances[0].identity.user_assigned_identities - - user_identity_2 in output.containerinstances[0].identity.user_assigned_identities - -- name: Remove container instance -- User Identity - azure_rm_containerinstance: - resource_group: "{{ resource_group }}" - name: "aci{{ rpfx }}fourth" - os_type: linux - ip_address: public - location: eastus - ports: - - 80 - containers: - - name: mycontainer1 - image: httpd - memory: 1.5 - ports: - - 80 - - 81 - identity: - type: UserAssigned - user_assigned_identities: - id: - - "{{ user_identity_1 }}" - - "{{ user_identity_2 }}" - state: absent - register: output - - name: Create sample container instance with volume azure_rm_containerinstance: resource_group: "{{ resource_group }}" @@ -462,15 +362,3 @@ ansible.builtin.assert: that: - output.changed == False - -- name: Destroy User Managed Identities - azure_rm_resource: - resource_group: "{{ resource_group }}" - provider: ManagedIdentity - resource_type: userAssignedIdentities - resource_name: "{{ item }}" - api_version: "2023-01-31" - state: absent - loop: - - "ansible-test-aci-identity" - - "ansible-test-aci-identity-2" diff --git a/tests/integration/targets/azure_rm_containerregistry/tasks/main.yml b/tests/integration/targets/azure_rm_containerregistry/tasks/main.yml index c727e16c2..b474b0e1f 100644 --- a/tests/integration/targets/azure_rm_containerregistry/tasks/main.yml +++ b/tests/integration/targets/azure_rm_containerregistry/tasks/main.yml @@ -1,36 +1,8 @@ -- name: Gather Resource Group info - azure.azcollection.azure_rm_resourcegroup_info: - name: "{{ resource_group }}" - register: __rg_info - -- name: Set Azure Region based on resource group location - ansible.builtin.set_fact: - location: "{{ __rg_info.resourcegroups.0.location }}" - -- name: Create User Managed Identities - azure_rm_resource: - resource_group: "{{ resource_group }}" - provider: ManagedIdentity - resource_type: userAssignedIdentities - resource_name: "{{ item }}" - api_version: "2023-01-31" - body: - location: "{{ location }}" - state: present - loop: - - "ansible-test-acr-identity" - - "ansible-test-acr-identity-2" - -- name: Set identities IDs to test. Identities ansible-test-acr-identity and ansible-test-acr-identity-2 have to be created previously - ansible.builtin.set_fact: - user_identity_1: "/subscriptions/{{ azure_subscription_id }}/resourcegroups/{{ resource_group }}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/ansible-test-acr-identity" - user_identity_2: "/subscriptions/{{ azure_subscription_id }}/resourcegroups/{{ resource_group }}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/ansible-test-acr-identity-2" - - name: Create an container registry azure_rm_containerregistry: name: "acr{{ resource_group | hash('md5') | truncate(7, True, '') }}" resource_group: "{{ resource_group }}" - location: "{{ location }}" + location: eastus2 admin_user_enabled: true sku: Premium tags: @@ -43,7 +15,7 @@ that: - output.changed - output.admin_user_enabled - - output.location == location + - output.location == 'eastus2' - output.sku == 'Premium' - output.tags['Environment'] == 'Production' - output.tags['Release'] == 'beta1' @@ -55,7 +27,7 @@ azure_rm_containerregistry: name: "acr{{ resource_group | hash('md5') | truncate(7, True, '') }}" resource_group: "{{ resource_group }}" - location: "{{ location }}" + location: eastus2 admin_user_enabled: false sku: Standard tags: @@ -68,7 +40,7 @@ azure_rm_containerregistry: name: "acr{{ resource_group | hash('md5') | truncate(7, True, '') }}sec" resource_group: "{{ resource_group }}" - location: "{{ location }}" + location: eastus2 admin_user_enabled: false sku: Premium tags: @@ -131,73 +103,6 @@ - output.registries[1]['id'] != None - output.registries[1]['credentials'] != None -- name: Update second container registry to test identity - azure_rm_containerregistry: - name: "acr{{ resource_group | hash('md5') | truncate(7, True, '') }}sec" - resource_group: "{{ resource_group }}" - location: "{{ location }}" - admin_user_enabled: false - sku: Premium - tags: - Release: beta1 - Environment: Production - identity: - type: UserAssigned - user_assigned_identities: - id: - - "{{ user_identity_1 }}" - register: output - -- name: Assert the container registry instance is well created - ansible.builtin.assert: - that: - - output.changed - - user_identity_1 in output.identity.user_assigned_identities - -- name: Update second container registry to test appending identity - azure_rm_containerregistry: - name: "acr{{ resource_group | hash('md5') | truncate(7, True, '') }}sec" - resource_group: "{{ resource_group }}" - location: "{{ location }}" - admin_user_enabled: false - sku: Premium - tags: - Release: beta1 - Environment: Production - identity: - type: UserAssigned - user_assigned_identities: - id: - - "{{ user_identity_2 }}" - register: output - -- name: Assert the container registry instance is well created - ansible.builtin.assert: - that: - - output.changed - - user_identity_1 in output.identity.user_assigned_identities - - user_identity_2 in output.identity.user_assigned_identities - -- name: Update second container registry to test System Identity - azure_rm_containerregistry: - name: "acr{{ resource_group | hash('md5') | truncate(7, True, '') }}sec" - resource_group: "{{ resource_group }}" - location: "{{ location }}" - admin_user_enabled: false - sku: Premium - tags: - Release: beta1 - Environment: Production - identity: - type: SystemAssigned - register: output - -- name: Assert the container registry instance is well created - ansible.builtin.assert: - that: - - output.changed - - '"user_assigned_identities" not in output.identity' - - name: Delete first container registry azure_rm_containerregistry: name: "acr{{ resource_group | hash('md5') | truncate(7, True, '') }}" @@ -209,15 +114,3 @@ name: "acr{{ resource_group | hash('md5') | truncate(7, True, '') }}sec" resource_group: "{{ resource_group }}" state: absent - -- name: Destroy User Managed Identities - azure_rm_resource: - resource_group: "{{ resource_group }}" - provider: ManagedIdentity - resource_type: userAssignedIdentities - resource_name: "{{ item }}" - api_version: "2023-01-31" - state: absent - loop: - - "ansible-test-acr-identity" - - "ansible-test-acr-identity-2" diff --git a/tests/integration/targets/azure_rm_gallery/tasks/main.yml b/tests/integration/targets/azure_rm_gallery/tasks/main.yml index 3389336dc..8270b04ce 100644 --- a/tests/integration/targets/azure_rm_gallery/tasks/main.yml +++ b/tests/integration/targets/azure_rm_gallery/tasks/main.yml @@ -109,7 +109,7 @@ azure_rm_virtualmachine_info: resource_group: "{{ resource_group }}" name: "vmforimage{{ rpfx }}" - register: vm_output + register: output - name: Create a snapshot by importing an unmanaged blob from the same subscription. azure_rm_snapshot: @@ -118,7 +118,7 @@ location: eastus creation_data: create_option: Import - source_uri: 'https://{{ vm_output.vms[0].storage_account_name }}.blob.core.windows.net/{{ vm_output.vms[0].storage_container_name }}/{{ vm_output.vms[0].storage_blob_name }}' + source_uri: 'https://{{ output.vms[0].storage_account_name }}.blob.core.windows.net/{{ output.vms[0].storage_container_name }}/{{ output.vms[0].storage_blob_name }}' register: output - name: Assert the snapshot created @@ -343,47 +343,6 @@ that: - output.changed -- name: Create or update a simple gallery Image Version. - azure_rm_galleryimageversion: - resource_group: "{{ resource_group }}" - gallery_name: myGallery{{ rpfx }} - gallery_image_name: myImage - name: 10.1.4 - location: eastus - publishing_profile: - end_of_life_date: "2050-10-01t00:00:00+00:00" - exclude_from_latest: true - replica_count: 3 - storage_account_type: Standard_LRS - target_regions: - - name: eastus - regional_replica_count: 1 - encryption: - data_disk_images: - - disk_encryption_set_id: "{{ des_results.state.id }}" - os_disk_image: - disk_encryption_set_id: "{{ des_results.state.id }}" - - name: westus - regional_replica_count: 2 - encryption: - data_disk_images: - - disk_encryption_set_id: "{{ des_results.state.id }}" - os_disk_image: - disk_encryption_set_id: "{{ des_results.state.id }}" - storage_account_type: Standard_ZRS - storage_profile: - os_disk: - source: - resource_group: "{{ resource_group }}" - storage_account: '{{ vm_output.vms[0].storage_account_name }}' - uri: 'https://{{ vm_output.vms[0].storage_account_name }}.blob.core.windows.net/{{ vm_output.vms[0].storage_container_name }}/{{ vm_output.vms[0].storage_blob_name }}' - register: output - -- name: Assert the gallery image version created - ansible.builtin.assert: - that: - - output.changed - - name: Create or update a simple gallery Image Version - idempotent azure_rm_galleryimageversion: resource_group: "{{ resource_group }}" @@ -480,20 +439,6 @@ - output.versions['publishing_profile'] != None - output.versions['provisioning_state'] != None -- name: Delete gallery image version from URI. - azure_rm_galleryimageversion: - resource_group: "{{ resource_group }}" - gallery_name: myGallery{{ rpfx }} - gallery_image_name: myImage - name: 10.1.4 - state: absent - register: output - -- name: Assert the gallery image version from URI deleted - ansible.builtin.assert: - that: - - output.changed - - name: Delete gallery image Version. azure_rm_galleryimageversion: resource_group: "{{ resource_group }}" diff --git a/tests/integration/targets/azure_rm_networkwatcher/aliases b/tests/integration/targets/azure_rm_networkwatcher/aliases deleted file mode 100644 index 9eb408856..000000000 --- a/tests/integration/targets/azure_rm_networkwatcher/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/azure -shippable/azure/group5 -destructive -disabled diff --git a/tests/integration/targets/azure_rm_networkwatcher/meta/main.yml b/tests/integration/targets/azure_rm_networkwatcher/meta/main.yml deleted file mode 100644 index 95e1952f9..000000000 --- a/tests/integration/targets/azure_rm_networkwatcher/meta/main.yml +++ /dev/null @@ -1,2 +0,0 @@ -dependencies: - - setup_azure diff --git a/tests/integration/targets/azure_rm_networkwatcher/tasks/main.yml b/tests/integration/targets/azure_rm_networkwatcher/tasks/main.yml deleted file mode 100644 index 2520c2acf..000000000 --- a/tests/integration/targets/azure_rm_networkwatcher/tasks/main.yml +++ /dev/null @@ -1,78 +0,0 @@ -- name: Set Random Variables - ansible.builtin.set_fact: - rpfx: "{{ resource_group | hash('md5') | truncate(20, True, '') }}" - -- name: Create a Network Watcher(Checkmode test) - azure_rm_networkwatcher: - resource_group: "{{ resource_group }}" - name: "mynetwacher{{ rpfx }}" - location: westus3 - tags: - testing: testing - delete: on-exit - check_mode: true - -- name: Create a new Network Watcher - azure_rm_networkwatcher: - resource_group: "{{ resource_group }}" - name: "mynetwacher{{ rpfx }}" - location: westus3 - tags: - testing: testing - delete: on-exit - register: output - -- name: Assert the network watcher is well created - ansible.builtin.assert: - that: - - output.changed - -- name: Create a Network Watcher again(Idempotent test) - azure_rm_networkwatcher: - resource_group: "{{ resource_group }}" - name: "mynetwacher{{ rpfx }}" - location: westus3 - tags: - testing: testing - delete: on-exit - register: output - -- name: Assert the network watcher is no change - ansible.builtin.assert: - that: - - not output.changed - -- name: Get the network watcher facts - azure_rm_networkwatcher_info: - resource_group: "{{ resource_group }}" - name: "mynetwacher{{ rpfx }}" - register: output - -- name: Assert the network wacher facts - ansible.builtin.assert: - that: - - output.network_watchers[0].tags | length == 2 - -- name: Get the network watcher facts and filter by tags - azure_rm_networkwatcher_info: - resource_group: "{{ resource_group }}" - tags: - - none-key - register: output - -- name: Assert the network wacher facts - ansible.builtin.assert: - that: - - output.network_watchers[0] == None - -- name: Delete the Network Watcher - azure_rm_networkwatcher: - resource_group: "{{ resource_group }}" - name: "mynetwacher{{ rpfx }}" - state: absent - register: output - -- name: Assert the network watcher is well delete - ansible.builtin.assert: - that: - - output.changed diff --git a/tests/integration/targets/azure_rm_openshiftmanagedcluster/tasks/main.yml b/tests/integration/targets/azure_rm_openshiftmanagedcluster/tasks/main.yml index 2473ef57f..3dd784e8a 100644 --- a/tests/integration/targets/azure_rm_openshiftmanagedcluster/tasks/main.yml +++ b/tests/integration/targets/azure_rm_openshiftmanagedcluster/tasks/main.yml @@ -58,19 +58,6 @@ address_prefix_cidr: 10.152.0.0/24 register: worker_sub_output -- name: Get available openshift cluster versions - azure_rm_openshiftmanagedclusterversion_info: - location: "eastus" - register: ocp_cl_vers - -- name: Extract the latest available version - ansible.builtin.set_fact: - ocp_version: "{{ ocp_cl_vers.versions | community.general.version_sort | last }}" - -- name: Assert that selected ocp version is not empty - ansible.builtin.assert: - that: ocp_version | length != 0 - - name: Create openshift cluster azure_rm_openshiftmanagedcluster: resource_group: "{{ resource_group }}" @@ -79,7 +66,6 @@ cluster_profile: cluster_resource_group_id: "{{ rg_output.resourcegroups[0].id }}" domain: "{{ cluster_name }}" - version: "{{ ocp_version }}" service_principal_profile: client_id: "{{ azure_client_id }}" client_secret: "{{ azure_secret }}" diff --git a/tests/integration/targets/azure_rm_storageaccount/tasks/main.yml b/tests/integration/targets/azure_rm_storageaccount/tasks/main.yml index 21db25529..942d4888a 100644 --- a/tests/integration/targets/azure_rm_storageaccount/tasks/main.yml +++ b/tests/integration/targets/azure_rm_storageaccount/tasks/main.yml @@ -578,67 +578,6 @@ - not output.storageaccounts[0].encryption.require_infrastructure_encryption - output.storageaccounts[0].encryption.services | length == 2 -- name: Create a storage account with allow_shared_key_access - azure_rm_storageaccount: - resource_group: "{{ resource_group }}" - name: "{{ storage_account_name_default }}07" - account_type: Standard_LRS - kind: StorageV2 - allow_shared_key_access: true - default_to_o_auth_authentication: true - allow_cross_tenant_replication: true - register: output - -- name: Assert storage account is well created - ansible.builtin.assert: - that: - - output.changed - -- name: Create a storage account with allow_shared_key_access(Idempotent test) - azure_rm_storageaccount: - resource_group: "{{ resource_group }}" - name: "{{ storage_account_name_default }}07" - account_type: Standard_LRS - kind: StorageV2 - allow_shared_key_access: true - default_to_o_auth_authentication: true - allow_cross_tenant_replication: true - register: output - -- name: Assert storage account no changed - ansible.builtin.assert: - that: - - not output.changed - -- name: Update the storage account - azure_rm_storageaccount: - resource_group: "{{ resource_group }}" - name: "{{ storage_account_name_default }}07" - account_type: Standard_LRS - kind: StorageV2 - allow_shared_key_access: false - default_to_o_auth_authentication: false - allow_cross_tenant_replication: false - register: output - -- name: Assert storage account is well updated - ansible.builtin.assert: - that: - - output.changed - -- name: Get the storage accounts facts - azure_rm_storageaccount_info: - resource_group: "{{ resource_group }}" - name: "{{ storage_account_name_default }}07" - register: output - -- name: Assert the storage accounts facts - ansible.builtin.assert: - that: - - output.storageaccounts[0].allow_cross_tenant_replication == false - - output.storageaccounts[0].allow_shared_key_access == false - - output.storageaccounts[0].default_to_o_auth_authentication == false - - name: List storage accounts by resource group. azure_rm_storageaccount_info: resource_group: "{{ resource_group }}" @@ -663,4 +602,3 @@ - "{{ storage_account_name_default }}04" - "{{ storage_account_name_default }}05" - "{{ storage_account_name_default }}06" - - "{{ storage_account_name_default }}07" diff --git a/tests/integration/targets/azure_rm_virtualmachinescaleset/tasks/main.yml b/tests/integration/targets/azure_rm_virtualmachinescaleset/tasks/main.yml index e80bf38b0..dd429406c 100644 --- a/tests/integration/targets/azure_rm_virtualmachinescaleset/tasks/main.yml +++ b/tests/integration/targets/azure_rm_virtualmachinescaleset/tasks/main.yml @@ -1,31 +1,3 @@ -- name: Gather Resource Group info - azure.azcollection.azure_rm_resourcegroup_info: - name: "{{ resource_group }}" - register: __rg_info - -- name: Set location based on resource group - ansible.builtin.set_fact: - location: "{{ __rg_info.resourcegroups.0.location }}" - -- name: Create User Managed Identities - azure_rm_resource: - resource_group: "{{ resource_group }}" - provider: ManagedIdentity - resource_type: userAssignedIdentities - resource_name: "{{ item }}" - api_version: "2023-01-31" - body: - location: "{{ location }}" - state: present - loop: - - "ansible-test-vmss-identity" - - "ansible-test-vmss-identity-2" - -- name: Set identities IDs to test. Identities ansible-test-vmss-identity and ansible-test-vmss-identity-2 have to be created previously - ansible.builtin.set_fact: - user_identity_1: "/subscriptions/{{ azure_subscription_id }}/resourcegroups/{{ resource_group }}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/ansible-test-vmss-identity" - user_identity_2: "/subscriptions/{{ azure_subscription_id }}/resourcegroups/{{ resource_group }}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/ansible-test-vmss-identity-2" - - name: Prepare random number ansible.builtin.set_fact: rpfx: "{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}" @@ -167,11 +139,6 @@ disk_size_gb: 64 caching: ReadWrite managed_disk_type: Standard_LRS - identity: - type: UserAssigned - user_assigned_identities: - id: - - "{{ user_identity_1 }}" register: results - name: Assert that VMSS can be created @@ -206,11 +173,6 @@ disk_size_gb: 64 caching: ReadWrite managed_disk_type: Standard_LRS - identity: - type: UserAssigned - user_assigned_identities: - id: - - "{{ user_identity_1 }}" register: results - name: Assert that VMSS can be created @@ -227,7 +189,6 @@ ansible.builtin.assert: that: - output_scaleset.vmss[0].orchestration_mode == "Flexible" - - user_identity_1 in output_scaleset.vmss[0].identity.user_assigned_identities - name: Delete VMSS azure_rm_virtualmachinescaleset: @@ -266,24 +227,14 @@ disk_size_gb: 64 caching: ReadWrite managed_disk_type: Standard_LRS - identity: - type: SystemAssigned, UserAssigned - user_assigned_identities: - id: - - "{{ user_identity_1 }}" register: results -- name: Debug - ansible.builtin.debug: - var: results - - name: Assert that VMSS was created using Spot Instance default values ansible.builtin.assert: that: - results.ansible_facts.azure_vmss.virtual_machine_profile.priority == 'Spot' - results.ansible_facts.azure_vmss.virtual_machine_profile.eviction_policy == 'Deallocate' - results.ansible_facts.azure_vmss.virtual_machine_profile.billing_profile.max_price == -1.0 - - user_identity_1 in results.ansible_facts.azure_vmss.identity.user_assigned_identities - name: Delete VMSS azure_rm_virtualmachinescaleset: @@ -972,15 +923,3 @@ name: invalid-image register: fail_missing_custom_image_dict failed_when: fail_missing_custom_image_dict.msg != "Error could not find image with name invalid-image" - -- name: Destroy User Managed Identities - azure_rm_resource: - resource_group: "{{ resource_group }}" - provider: ManagedIdentity - resource_type: userAssignedIdentities - resource_name: "{{ item }}" - api_version: "2023-01-31" - state: absent - loop: - - "ansible-test-vmss-identity" - - "ansible-test-vmss-identity-2"