diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-18 05:52:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-18 05:52:35 +0000 |
commit | 7fec0b69a082aaeec72fee0612766aa42f6b1b4d (patch) | |
tree | efb569b86ca4da888717f5433e757145fa322e08 /ansible_collections/azure/azcollection/plugins | |
parent | Releasing progress-linux version 7.7.0+dfsg-3~progress7.99u1. (diff) | |
download | ansible-7fec0b69a082aaeec72fee0612766aa42f6b1b4d.tar.xz ansible-7fec0b69a082aaeec72fee0612766aa42f6b1b4d.zip |
Merging upstream version 9.4.0+dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/azure/azcollection/plugins')
269 files changed, 6947 insertions, 5237 deletions
diff --git a/ansible_collections/azure/azcollection/plugins/inventory/azure_rm.py b/ansible_collections/azure/azcollection/plugins/inventory/azure_rm.py index e570b59a9..3442aa124 100644 --- a/ansible_collections/azure/azcollection/plugins/inventory/azure_rm.py +++ b/ansible_collections/azure/azcollection/plugins/inventory/azure_rm.py @@ -35,6 +35,7 @@ EXAMPLES = ''' # vmid: the VM's internal SMBIOS ID, eg: '36bca69d-c365-4584-8c06-a62f4a1dc5d2' # vmss: if the VM is a member of a scaleset (vmss), a dictionary including the id and name of the parent scaleset # availability_zone: availability zone in which VM is deployed, eg '1','2','3' +# creation_time: datetime object of when the VM was created, eg '2023-07-21T09:30:30.4710164+00:00' # # The following host variables are sometimes availble: # computer_name: the Operating System's hostname. Will not be available if azure agent is not available and picking it up. @@ -51,58 +52,59 @@ auth_source: cli # fetches VMs from an explicit list of resource groups instead of default all (- '*') include_vm_resource_groups: -- myrg1 -- myrg2 + - myrg1 + - myrg2 # fetches VMs from VMSSs in all resource groups (defaults to no VMSS fetch) include_vmss_resource_groups: -- '*' + - '*' # places a host in the named group if the associated condition evaluates to true conditional_groups: - # since this will be true for every host, every host sourced from this inventory plugin config will be in the - # group 'all_the_hosts' - all_the_hosts: true - # if the VM's "name" variable contains "dbserver", it will be placed in the 'db_hosts' group - db_hosts: "'dbserver' in name" + # since this will be true for every host, every host sourced from this inventory plugin config will be in the + # group 'all_the_hosts' + all_the_hosts: true + # if the VM's "name" variable contains "dbserver", it will be placed in the 'db_hosts' group + db_hosts: "'dbserver' in name" # adds variables to each host found by this inventory plugin, whose values are the result of the associated expression hostvar_expressions: - my_host_var: - # A statically-valued expression has to be both single and double-quoted, or use escaped quotes, since the outer - # layer of quotes will be consumed by YAML. Without the second set of quotes, it interprets 'staticvalue' as a - # variable instead of a string literal. - some_statically_valued_var: "'staticvalue'" - # overrides the default ansible_host value with a custom Jinja2 expression, in this case, the first DNS hostname, or - # if none are found, the first public IP address. - ansible_host: (public_dns_hostnames + public_ipv4_addresses) | first + my_host_var: + # A statically-valued expression has to be both single and double-quoted, or use escaped quotes, since the outer + # layer of quotes will be consumed by YAML. Without the second set of quotes, it interprets 'staticvalue' as a + # variable instead of a string literal. + some_statically_valued_var: "'staticvalue'" + # overrides the default ansible_host value with a custom Jinja2 expression, in this case, the first DNS hostname, or + # if none are found, the first public IP address. + ansible_host: (public_dns_hostnames + public_ipv4_addresses) | first # change how inventory_hostname is generated. Each item is a jinja2 expression similar to hostvar_expressions. hostnames: - - tags.vm_name - - default # special var that uses the default hashed name + - tags.vm_name + - default_inventory_hostname + ".domain.tld" # Transfer to fqdn if you use shortnames for VMs + - default # special var that uses the default hashed name # places hosts in dynamically-created groups based on a variable value. keyed_groups: # places each host in a group named 'tag_(tag name)_(tag value)' for each tag on a VM. -- prefix: tag - key: tags + - prefix: tag + key: tags # places each host in a group named 'azure_loc_(location name)', depending on the VM's location -- prefix: azure_loc - key: location + - prefix: azure_loc + key: location # places host in a group named 'some_tag_X' using the value of the 'sometag' tag on a VM as X, and defaulting to the # value 'none' (eg, the group 'some_tag_none') if the 'sometag' tag is not defined for a VM. -- prefix: some_tag - key: tags.sometag | default('none') + - prefix: some_tag + key: tags.sometag | default('none') # excludes a host from the inventory when any of these expressions is true, can refer to any vars defined on the host exclude_host_filters: -# excludes hosts in the eastus region -- location in ['eastus'] -- tags['tagkey'] is defined and tags['tagkey'] == 'tagkey' -- tags['tagkey2'] is defined and tags['tagkey2'] == 'tagkey2' -# excludes hosts that are powered off -- powerstate != 'running' + # excludes hosts in the eastus region + - location in ['eastus'] + - tags['tagkey'] is defined and tags['tagkey'] == 'tagkey' + - tags['tagkey2'] is defined and tags['tagkey2'] == 'tagkey2' + # excludes hosts that are powered off + - powerstate != 'running' ''' # FUTURE: do we need a set of sane default filters, separate from the user-defineable ones? @@ -121,7 +123,6 @@ except ImportError: from Queue import Queue, Empty from collections import namedtuple -from ansible import release from ansible.plugins.inventory import BaseInventoryPlugin, Constructable from ansible.module_utils.six import iteritems from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMAuth @@ -131,21 +132,19 @@ from ansible.module_utils._text import to_native, to_bytes, to_text from itertools import chain try: - from msrest import ServiceClient, Serializer, Deserializer - from msrestazure import AzureConfiguration - from msrestazure.polling.arm_polling import ARMPolling - from msrestazure.tools import parse_resource_id + from azure.core._pipeline_client import PipelineClient + from azure.core.pipeline.policies import BearerTokenCredentialPolicy + from azure.core.configuration import Configuration + from azure.mgmt.core.tools import parse_resource_id except ImportError: - AzureConfiguration = object - ARMPolling = object + Configuration = object parse_resource_id = object - ServiceClient = object - Serializer = object - Deserializer = object + PipelineClient = object + BearerTokenCredentialPolicy = object pass -class AzureRMRestConfiguration(AzureConfiguration): +class AzureRMRestConfiguration(Configuration): def __init__(self, credentials, subscription_id, base_url=None): if credentials is None: @@ -155,10 +154,11 @@ class AzureRMRestConfiguration(AzureConfiguration): if not base_url: base_url = 'https://management.azure.com' - super(AzureRMRestConfiguration, self).__init__(base_url) + credential_scopes = base_url + '/.default' - self.add_user_agent('ansible-dynamic-inventory/{0}'.format(release.__version__)) + super(AzureRMRestConfiguration, self).__init__() + self.authentication_policy = BearerTokenCredentialPolicy(credentials, credential_scopes) self.credentials = credentials self.subscription_id = subscription_id @@ -174,13 +174,11 @@ class InventoryModule(BaseInventoryPlugin, Constructable): def __init__(self): super(InventoryModule, self).__init__() - self._serializer = Serializer() - self._deserializer = Deserializer() self._hosts = [] self._filters = None # FUTURE: use API profiles with defaults - self._compute_api_version = '2017-03-30' + self._compute_api_version = '2021-11-01' self._network_api_version = '2015-06-15' self._default_header_parameters = {'Content-Type': 'application/json; charset=utf-8'} @@ -236,14 +234,16 @@ class InventoryModule(BaseInventoryPlugin, Constructable): cloud_environment=self.get_option('cloud_environment'), cert_validation_mode=self.get_option('cert_validation_mode'), api_profile=self.get_option('api_profile'), + track1_cred=True, adfs_authority_url=self.get_option('adfs_authority_url') ) self.azure_auth = AzureRMAuth(**auth_options) - self._clientconfig = AzureRMRestConfiguration(self.azure_auth.azure_credentials, self.azure_auth.subscription_id, + self._clientconfig = AzureRMRestConfiguration(self.azure_auth.azure_credential_track2, self.azure_auth.subscription_id, self.azure_auth._cloud_environment.endpoints.resource_manager) - self._client = ServiceClient(self._clientconfig.credentials, self._clientconfig) + + self.new_client = PipelineClient(self.azure_auth._cloud_environment.endpoints.resource_manager, config=self._clientconfig) def _enqueue_get(self, url, api_version, handler, handler_args=None): if not handler_args: @@ -399,7 +399,9 @@ class InventoryModule(BaseInventoryPlugin, Constructable): name = str(uuid.uuid4()) query_parameters = {'api-version': item.api_version} - req = self._client.get(item.url, query_parameters) + header_parameters = {'x-ms-client-request-id': str(uuid.uuid4()), 'Content-Type': 'application/json; charset=utf-8'} + body = {} + req = self.new_client.get(item.url, query_parameters, header_parameters, body) batch_requests.append(dict(httpMethod="GET", url=req.url, name=name)) batch_response_handlers[name] = item batch_item_index += 1 @@ -431,36 +433,25 @@ class InventoryModule(BaseInventoryPlugin, Constructable): def _send_batch(self, batched_requests): url = '/batch' query_parameters = {'api-version': '2015-11-01'} - - body_obj = dict(requests=batched_requests) - - body_content = self._serializer.body(body_obj, 'object') + header_parameters = {'x-ms-client-request-id': str(uuid.uuid4()), 'Content-Type': 'application/json; charset=utf-8'} + body_content = dict(requests=batched_requests) header = {'x-ms-client-request-id': str(uuid.uuid4())} header.update(self._default_header_parameters) - request = self._client.post(url, query_parameters) - initial_response = self._client.send(request, header, body_content) + request_new = self.new_client.post(url, query_parameters, header_parameters, body_content) + response = self.new_client.send_request(request_new) - # FUTURE: configurable timeout? - poller = ARMPolling(timeout=2) - poller.initialize(client=self._client, - initial_response=initial_response, - deserialization_callback=lambda r: self._deserializer('object', r)) - - poller.run() - - return poller.resource() + return json.loads(response.body()) def send_request(self, url, api_version): query_parameters = {'api-version': api_version} - req = self._client.get(url, query_parameters) - resp = self._client.send(req, self._default_header_parameters, stream=False) - - resp.raise_for_status() - content = resp.content + header_parameters = {'x-ms-client-request-id': str(uuid.uuid4()), 'Content-Type': 'application/json; charset=utf-8'} + body = {} + request_new = self.new_client.get(url, query_parameters, header_parameters) + response = self.new_client.send_request(request_new) - return json.loads(content) + return json.loads(response.body()) @staticmethod def _legacy_script_compatible_group_sanitization(name): @@ -558,6 +549,7 @@ class AzureHost(object): plan=self._vm_model['properties']['plan']['name'] if self._vm_model['properties'].get('plan') else None, resource_group=parse_resource_id(self._vm_model['id']).get('resource_group').lower(), default_inventory_hostname=self.default_inventory_hostname, + creation_time=self._vm_model['properties']['timeCreated'], ) # set nic-related values from the primary NIC first diff --git a/ansible_collections/azure/azcollection/plugins/lookup/azure_keyvault_secret.py b/ansible_collections/azure/azcollection/plugins/lookup/azure_keyvault_secret.py index a3c809fd6..ea2183a5a 100644 --- a/ansible_collections/azure/azcollection/plugins/lookup/azure_keyvault_secret.py +++ b/ansible_collections/azure/azcollection/plugins/lookup/azure_keyvault_secret.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Hai Cao, <t-haicao@microsoft.com> +# Copyright (c) 2022 Hai Cao, <t-haicao@microsoft.com>, Marcin Slowikowski (@msl0) # # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) @@ -10,11 +10,11 @@ DOCUMENTATION = """ name: azure_keyvault_secret author: - Hai Cao (@tk5eq) <t-haicao@microsoft.com> + - Marcin Slowikowski (@msl0) version_added: '1.12.0' requirements: - requests - azure - - msrest short_description: Read secret from Azure Key Vault. description: - This lookup returns the content of secret saved in Azure Key Vault. @@ -32,21 +32,23 @@ options: description: Secret of the service principal. tenant_id: description: Tenant id of service principal. - subscription_id: - description: Your Azure subscription Id. notes: - If version is not provided, this plugin will return the latest version of the secret. - If ansible is running on Azure Virtual Machine with MSI enabled, client_id, secret and tenant isn't required. - For enabling MSI on Azure VM, please refer to this doc https://docs.microsoft.com/en-us/azure/active-directory/managed-service-identity/ - After enabling MSI on Azure VM, remember to grant access of the Key Vault to the VM by adding a new Acess Policy in Azure Portal. - If MSI is not enabled on ansible host, it's required to provide a valid service principal which has access to the key vault. + - To authenticate via service principal, pass client_id, secret and tenant_id or set environment variables + AZURE_CLIENT_ID, AZURE_CLIENT_SECRET and AZURE_TENANT_ID. + - Authentication via C(az login) is also supported. - To use a plugin from a collection, please reference the full namespace, collection name, and lookup plugin name that you want to use. """ EXAMPLE = """ - name: Look up secret when azure cli login debug: - msg: msg: "{{ lookup('azure.azcollection.azure_keyvault_secret', 'testsecret', vault_url=key_vault_uri, subscription_id=subscription_id)}}" + msg: msg: "{{ lookup('azure.azcollection.azure_keyvault_secret', 'testsecret', vault_url=key_vault_uri)}}" + - name: Look up secret when ansible host is MSI enabled Azure VM debug: msg: "the value of this secret is {{ @@ -98,9 +100,9 @@ EXAMPLE = """ key_data: "{{ ssh_key }}" network_interfaces: "{{ vm_name }}" image: - offer: UbuntuServer + offer: 0001-com-ubuntu-server-focal publisher: Canonical - sku: 16.04-LTS + sku: 20_04-lts version: latest """ @@ -109,17 +111,16 @@ RETURN = """ description: secret content string """ -from ansible.errors import AnsibleError, AnsibleParserError +from ansible.errors import AnsibleError from ansible.plugins.lookup import LookupBase from ansible.utils.display import Display try: - import requests import logging - import os - from azure.common.credentials import ServicePrincipalCredentials, get_cli_profile - from azure.keyvault import KeyVaultClient - from msrest.exceptions import AuthenticationError, ClientRequestError - from azure.keyvault.models.key_vault_error import KeyVaultErrorException + import requests + from azure.keyvault.secrets import SecretClient + from azure.identity import DefaultAzureCredential, ClientSecretCredential + from azure.keyvault.secrets import SecretClient + except ImportError: pass @@ -127,6 +128,8 @@ display = Display() TOKEN_ACQUIRED = False +logger = logging.getLogger("azure.identity").setLevel(logging.ERROR) + token_params = { 'api-version': '2018-02-01', 'resource': 'https://vault.azure.net' @@ -154,37 +157,27 @@ except Exception: def lookup_secret_non_msi(terms, vault_url, kwargs): - logging.getLogger('msrestazure.azure_active_directory').addHandler(logging.NullHandler()) - logging.getLogger('msrest.service_client').addHandler(logging.NullHandler()) - - client_id = kwargs['client_id'] if kwargs.get('client_id') else os.environ.get('AZURE_CLIENT_ID') - secret = kwargs['secret'] if kwargs.get('secret') else os.environ.get('AZURE_SECRET') - tenant_id = kwargs['tenant_id'] if kwargs.get('tenant_id') else os.environ.get('AZURE_TENANT') - subscription_id = kwargs['subscription_id'] if kwargs.get('subscription_id') else os.environ.get('AZURE_SUBSCRIPTION_ID') - - try: - if client_id is not None and secret is not None and tenant_id is not None: - credentials = ServicePrincipalCredentials( - client_id=client_id, - secret=secret, - tenant=tenant_id - ) - elif subscription_id is not None: - profile = get_cli_profile() - credentials, subscription_id, tenant = profile.get_login_credentials( - subscription_id=subscription_id, resource="https://vault.azure.net") - client = KeyVaultClient(credentials) - except AuthenticationError: - raise AnsibleError('Invalid credentials provided.') + + client_id = kwargs['client_id'] if kwargs.get('client_id') else None + secret = kwargs['secret'] if kwargs.get('secret') else None + tenant_id = kwargs['tenant_id'] if kwargs.get('tenant_id') else None + + if all(v is not None for v in [client_id, secret, tenant_id]): + credential = ClientSecretCredential( + tenant_id=tenant_id, + client_id=client_id, + client_secret=secret, + ) + else: + credential = DefaultAzureCredential() + client = SecretClient(vault_url, credential) ret = [] for term in terms: try: - secret_val = client.get_secret(vault_url, term, '').value + secret_val = client.get_secret(term).value ret.append(secret_val) - except ClientRequestError: - raise AnsibleError('Error occurred in request') - except KeyVaultErrorException: + except Exception: raise AnsibleError('Failed to fetch secret ' + term + '.') return ret diff --git a/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common.py b/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common.py index 42026fac1..9c0e6e839 100644 --- a/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common.py +++ b/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common.py @@ -202,9 +202,6 @@ HAS_AZURE_EXC = None HAS_AZURE_CLI_CORE = True HAS_AZURE_CLI_CORE_EXC = None -HAS_MSRESTAZURE = True -HAS_MSRESTAZURE_EXC = None - try: import importlib except ImportError: @@ -221,21 +218,12 @@ except ImportError: HAS_PACKAGING_VERSION = False HAS_PACKAGING_VERSION_EXC = traceback.format_exc() -# NB: packaging issue sometimes cause msrestazure not to be installed, check it separately -try: - from msrest.serialization import Serializer -except ImportError: - HAS_MSRESTAZURE_EXC = traceback.format_exc() - HAS_MSRESTAZURE = False - try: from enum import Enum from msrestazure.azure_active_directory import AADTokenCredentials - from msrestazure.azure_exceptions import CloudError from msrestazure.azure_active_directory import MSIAuthentication - from azure.cli.core.auth.adal_authentication import MSIAuthenticationWrapper - from msrestazure.tools import parse_resource_id, resource_id, is_valid_resource_id - from msrestazure import azure_cloud + from azure.mgmt.core.tools import parse_resource_id, resource_id, is_valid_resource_id + from azure.cli.core import cloud as azure_cloud from azure.common.credentials import ServicePrincipalCredentials, UserPassCredentials from azure.mgmt.network import NetworkManagementClient from azure.mgmt.resource.resources import ResourceManagementClient @@ -252,11 +240,10 @@ try: from azure.mgmt.marketplaceordering import MarketplaceOrderingAgreements from azure.mgmt.trafficmanager import TrafficManagerManagementClient from azure.storage.blob import BlobServiceClient - from adal.authentication_context import AuthenticationContext + from msal.application import ClientApplication, ConfidentialClientApplication from azure.mgmt.authorization import AuthorizationManagementClient from azure.mgmt.sql import SqlManagementClient from azure.mgmt.servicebus import ServiceBusManagementClient - import azure.mgmt.servicebus.models as ServicebusModel from azure.mgmt.rdbms.postgresql import PostgreSQLManagementClient from azure.mgmt.rdbms.mysql import MySQLManagementClient from azure.mgmt.rdbms.mariadb import MariaDBManagementClient @@ -268,9 +255,6 @@ try: import azure.mgmt.automation.models as AutomationModel from azure.mgmt.iothub import IotHubClient from azure.mgmt.iothub import models as IoTHubModels - from msrest.service_client import ServiceClient - from msrestazure import AzureConfiguration - from msrest.authentication import Authentication from azure.mgmt.resource.locks import ManagementLockClient from azure.mgmt.recoveryservicesbackup import RecoveryServicesBackupClient import azure.mgmt.recoveryservicesbackup.models as RecoveryServicesBackupModels @@ -281,7 +265,7 @@ try: from azure.mgmt.eventhub import EventHubManagementClient from azure.mgmt.datafactory import DataFactoryManagementClient import azure.mgmt.datafactory.models as DataFactoryModel - from azure.identity._credentials import client_secret, user_password, certificate + from azure.identity._credentials import client_secret, user_password, certificate, managed_identity except ImportError as exc: Authentication = object @@ -411,10 +395,6 @@ class AzureRMModuleBase(object): self.fail(msg=missing_required_lib('packaging'), exception=HAS_PACKAGING_VERSION_EXC) - if not HAS_MSRESTAZURE: - self.fail(msg=missing_required_lib('msrestazure'), - exception=HAS_MSRESTAZURE_EXC) - if not HAS_AZURE: self.fail(msg=missing_required_lib('ansible[azure] (azure >= {0})'.format(AZURE_MIN_RELEASE)), exception=HAS_AZURE_EXC) @@ -594,8 +574,6 @@ class AzureRMModuleBase(object): ''' try: return self.rm_client.resource_groups.get(resource_group) - except CloudError as cloud_error: - self.fail("Error retrieving resource group {0} - {1}".format(resource_group, cloud_error.message)) except Exception as exc: self.fail("Error retrieving resource group {0} - {1}".format(resource_group, str(exc))) @@ -619,18 +597,7 @@ class AzureRMModuleBase(object): :param enum_modules: List of module names to build enum dependencies from. :return: serialized result ''' - enum_modules = [] if enum_modules is None else enum_modules - - dependencies = dict() - if enum_modules: - for module_name in enum_modules: - mod = importlib.import_module(module_name) - for mod_class_name, mod_class_obj in inspect.getmembers(mod, predicate=inspect.isclass): - dependencies[mod_class_name] = mod_class_obj - self.log("dependencies: ") - self.log(str(dependencies)) - serializer = Serializer(classes=dependencies) - return serializer.body(obj, class_name, keep_readonly=True) + return obj.as_dict() def get_poller_result(self, poller, wait=5): ''' @@ -998,13 +965,6 @@ class AzureRMModuleBase(object): result['skn'] = policy return 'SharedAccessSignature ' + urlencode(result) - def get_data_svc_client(self, **kwags): - url = kwags.get('base_url', None) - config = AzureConfiguration(base_url='https://{0}'.format(url)) - config.credentials = AzureSASAuthentication(token=self.generate_sas_token(**kwags)) - config = self.add_user_agent(config) - return ServiceClient(creds=config.credentials, config=config) - def get_subnet_detail(self, subnet_id): vnet_detail = subnet_id.split('/Microsoft.Network/virtualNetworks/')[1].split('/subnets/') return dict( @@ -1454,22 +1414,6 @@ class AzureRMModuleBase(object): return DataFactoryModel -class AzureSASAuthentication(Authentication): - """Simple SAS Authentication. - An implementation of Authentication in - https://github.com/Azure/msrest-for-python/blob/0732bc90bdb290e5f58c675ffdd7dbfa9acefc93/msrest/authentication.py - - :param str token: SAS token - """ - def __init__(self, token): - self.token = token - - def signed_session(self): - session = super(AzureSASAuthentication, self).signed_session() - session.headers['Authorization'] = self.token - return session - - class AzureRMAuthException(Exception): pass @@ -1481,7 +1425,7 @@ class AzureRMAuth(object): def __init__(self, auth_source=None, profile=None, subscription_id=None, client_id=None, secret=None, tenant=None, ad_user=None, password=None, cloud_environment='AzureCloud', cert_validation_mode='validate', api_profile='latest', adfs_authority_url=None, fail_impl=None, is_ad_resource=False, - x509_certificate_path=None, thumbprint=None, **kwargs): + x509_certificate_path=None, thumbprint=None, track1_cred=False, **kwargs): if fail_impl: self._fail_impl = fail_impl @@ -1560,11 +1504,13 @@ class AzureRMAuth(object): if self.credentials.get('auth_source') == 'msi': # MSI Credentials - self.azure_credentials = self.credentials['credentials'] + if is_ad_resource or track1_cred: + self.azure_credentials = self.credentials['credentials'] self.azure_credential_track2 = self.credentials['credential'] elif self.credentials.get('credentials') is not None: # AzureCLI credentials - self.azure_credentials = self.credentials['credentials'] + if is_ad_resource or track1_cred: + self.azure_credentials = self.credentials['credentials'] self.azure_credential_track2 = self.credentials['credentials'] elif self.credentials.get('client_id') is not None and \ self.credentials.get('secret') is not None and \ @@ -1572,63 +1518,70 @@ class AzureRMAuth(object): graph_resource = self._cloud_environment.endpoints.active_directory_graph_resource_id rm_resource = self._cloud_environment.endpoints.resource_manager - self.azure_credentials = ServicePrincipalCredentials(client_id=self.credentials['client_id'], - secret=self.credentials['secret'], - tenant=self.credentials['tenant'], - cloud_environment=self._cloud_environment, - resource=graph_resource if self.is_ad_resource else rm_resource, - verify=self._cert_validation_mode == 'validate') + if is_ad_resource or track1_cred: + self.azure_credentials = ServicePrincipalCredentials(client_id=self.credentials['client_id'], + secret=self.credentials['secret'], + tenant=self.credentials['tenant'], + cloud_environment=self._cloud_environment, + resource=graph_resource if self.is_ad_resource else rm_resource, + verify=self._cert_validation_mode == 'validate') self.azure_credential_track2 = client_secret.ClientSecretCredential(client_id=self.credentials['client_id'], client_secret=self.credentials['secret'], - tenant_id=self.credentials['tenant']) + tenant_id=self.credentials['tenant'], + authority=self._adfs_authority_url) elif self.credentials.get('client_id') is not None and \ self.credentials.get('tenant') is not None and \ self.credentials.get('thumbprint') is not None and \ self.credentials.get('x509_certificate_path') is not None: - - self.azure_credentials = self.acquire_token_with_client_certificate( - self._adfs_authority_url, - self._cloud_environment.endpoints.active_directory_resource_id, - self.credentials['x509_certificate_path'], - self.credentials['thumbprint'], - self.credentials['client_id'], - self.credentials['tenant']) + if is_ad_resource or track1_cred: + self.azure_credentials = self.acquire_token_with_client_certificate( + self._adfs_authority_url, + self.credentials['x509_certificate_path'], + self.credentials['thumbprint'], + self.credentials['client_id'], + self.credentials['tenant']) self.azure_credential_track2 = certificate.CertificateCredential(tenant_id=self.credentials['tenant'], client_id=self.credentials['client_id'], - certificate_path=self.credentials['x509_certificate_path']) + certificate_path=self.credentials['x509_certificate_path'], + authority=self._adfs_authority_url) + + elif self.credentials.get('ad_user') is not None and \ + self.credentials.get('password') is not None and \ + self.credentials.get('client_id') is not None and \ + self.credentials.get('tenant') is not None: + if is_ad_resource or track1_cred: + self.azure_credentials = self.acquire_token_with_username_password( + self._adfs_authority_url, + self.credentials['ad_user'], + self.credentials['password'], + self.credentials['client_id'], + self.credentials['tenant']) + self.azure_credential_track2 = user_password.UsernamePasswordCredential(username=self.credentials['ad_user'], + password=self.credentials['password'], + tenant_id=self.credentials.get('tenant'), + client_id=self.credentials.get('client_id'), + authority=self._adfs_authority_url) elif self.credentials.get('ad_user') is not None and self.credentials.get('password') is not None: tenant = self.credentials.get('tenant') if not tenant: tenant = 'common' # SDK default - self.azure_credentials = UserPassCredentials(self.credentials['ad_user'], - self.credentials['password'], - tenant=tenant, - cloud_environment=self._cloud_environment, - verify=self._cert_validation_mode == 'validate') + if is_ad_resource or track1_cred: + self.azure_credentials = UserPassCredentials(self.credentials['ad_user'], + self.credentials['password'], + tenant=tenant, + cloud_environment=self._cloud_environment, + verify=self._cert_validation_mode == 'validate') client_id = self.credentials.get('client_id', '04b07795-8ddb-461a-bbee-02f9e1bf7b46') - self.azure_credential_track2 = user_password.UsernamePasswordCredential(username=self.credentials['ad_user'], password=self.credentials['password'], tenant_id=self.credentials.get('tenant', 'organizations'), - client_id=client_id) - - elif self.credentials.get('ad_user') is not None and \ - self.credentials.get('password') is not None and \ - self.credentials.get('client_id') is not None and \ - self.credentials.get('tenant') is not None: - - self.azure_credentials = self.acquire_token_with_username_password( - self._adfs_authority_url, - self._cloud_environment.endpoints.active_directory_resource_id, - self.credentials['ad_user'], - self.credentials['password'], - self.credentials['client_id'], - self.credentials['tenant']) + client_id=client_id, + authority=self._adfs_authority_url) else: self.fail("Failed to authenticate with provided credentials. Some attributes were missing. " @@ -1688,12 +1641,12 @@ class AzureRMAuth(object): self.fail("cloud_environment {0} could not be resolved: {1}".format(_cloud_environment, str(exc)), exception=traceback.format_exc()) credentials = MSIAuthentication(client_id=client_id, cloud_environment=cloud_environment) - credential = MSIAuthenticationWrapper(client_id=client_id, cloud_environment=cloud_environment) + credential = managed_identity.ManagedIdentityCredential(client_id=client_id, cloud_environment=cloud_environment) subscription_id = subscription_id or self._get_env('subscription_id') if not subscription_id: try: # use the first subscription of the MSI - subscription_client = SubscriptionClient(credentials) + subscription_client = SubscriptionClient(credential) subscription = next(subscription_client.subscriptions.list()) subscription_id = str(subscription.subscription_id) except Exception as exc: @@ -1809,28 +1762,39 @@ class AzureRMAuth(object): return None - def acquire_token_with_username_password(self, authority, resource, username, password, client_id, tenant): + def acquire_token_with_username_password(self, authority, username, password, client_id, tenant): authority_uri = authority if tenant is not None: authority_uri = authority + '/' + tenant - context = AuthenticationContext(authority_uri) - token_response = context.acquire_token_with_username_password(resource, username, password, client_id) + context = ClientApplication(client_id=client_id, authority=authority_uri) + base_url = self._cloud_environment.endpoints.resource_manager + if not base_url.endswith("/"): + base_url += "/" + scopes = [base_url + ".default"] + token_response = context.acquire_token_by_username_password(username, password, scopes) return AADTokenCredentials(token_response) - def acquire_token_with_client_certificate(self, authority, resource, x509_certificate_path, thumbprint, client_id, tenant): + def acquire_token_with_client_certificate(self, authority, x509_private_key_path, thumbprint, client_id, tenant): authority_uri = authority if tenant is not None: authority_uri = authority + '/' + tenant - context = AuthenticationContext(authority_uri) - x509_certificate = None - with open(x509_certificate_path, 'rb') as pem_file: - x509_certificate = pem_file.read() - token_response = context.acquire_token_with_client_certificate(resource, client_id, x509_certificate, thumbprint) + x509_private_key = None + with open(x509_private_key_path, 'r') as pem_file: + x509_private_key = pem_file.read() + + base_url = self._cloud_environment.endpoints.resource_manager + if not base_url.endswith("/"): + base_url += "/" + scopes = [base_url + ".default"] + client_credential = {"thumbprint": thumbprint, "private_key": x509_private_key} + context = ConfidentialClientApplication(client_id=client_id, authority=authority_uri, client_credential=client_credential) + + token_response = context.acquire_token_for_client(scopes=scopes) return AADTokenCredentials(token_response) diff --git a/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common_ext.py b/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common_ext.py index df477c89b..0229e1027 100644 --- a/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common_ext.py +++ b/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common_ext.py @@ -7,8 +7,7 @@ __metaclass__ = type from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase -import re -from ansible.module_utils.common.dict_transformations import _camel_to_snake, _snake_to_camel +from ansible.module_utils.common.dict_transformations import _snake_to_camel from ansible.module_utils.six import string_types diff --git a/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common_rest.py b/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common_rest.py index 30908be53..6acb1e7b9 100644 --- a/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common_rest.py +++ b/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common_rest.py @@ -12,45 +12,45 @@ except Exception: ANSIBLE_VERSION = 'unknown' try: - from msrestazure.azure_exceptions import CloudError - from msrestazure.azure_configuration import AzureConfiguration - from msrest.service_client import ServiceClient - from msrest.pipeline import ClientRawResponse - from msrest.polling import LROPoller - from msrestazure.polling.arm_polling import ARMPolling + from azure.core._pipeline_client import PipelineClient + from azure.core.polling import LROPoller + from azure.core.pipeline import PipelineResponse + from azure.core.pipeline.policies import BearerTokenCredentialPolicy + from azure.mgmt.core.polling.arm_polling import ARMPolling import uuid - import json + from azure.core.configuration import Configuration except ImportError: # This is handled in azure_rm_common - AzureConfiguration = object + Configuration = object ANSIBLE_USER_AGENT = 'Ansible/{0}'.format(ANSIBLE_VERSION) -class GenericRestClientConfiguration(AzureConfiguration): +class GenericRestClientConfiguration(Configuration): - def __init__(self, credentials, subscription_id, base_url=None): + def __init__(self, credential, subscription_id, credential_scopes=None, base_url=None): - if credentials is None: + if credential is None: raise ValueError("Parameter 'credentials' must not be None.") if subscription_id is None: raise ValueError("Parameter 'subscription_id' must not be None.") if not base_url: base_url = 'https://management.azure.com' + if not credential_scopes: + credential_scopes = 'https://management.azure.com/.default' - super(GenericRestClientConfiguration, self).__init__(base_url) + super(GenericRestClientConfiguration, self).__init__() - self.add_user_agent(ANSIBLE_USER_AGENT) - - self.credentials = credentials + self.credentials = credential self.subscription_id = subscription_id + self.authentication_policy = BearerTokenCredentialPolicy(credential, credential_scopes) class GenericRestClient(object): - def __init__(self, credentials, subscription_id, base_url=None): - self.config = GenericRestClientConfiguration(credentials, subscription_id, base_url) - self._client = ServiceClient(self.config.credentials, self.config) + def __init__(self, credential, subscription_id, base_url=None, credential_scopes=None): + self.config = GenericRestClientConfiguration(credential, subscription_id, credential_scopes[0]) + self._client = PipelineClient(base_url, config=self.config) self.models = None def query(self, url, method, query_parameters, header_parameters, body, expected_status_codes, polling_timeout, polling_interval): @@ -65,31 +65,30 @@ class GenericRestClient(object): header_parameters['x-ms-client-request-id'] = str(uuid.uuid1()) if method == 'GET': - request = self._client.get(url, query_parameters) + request = self._client.get(url, query_parameters, header_parameters, body) elif method == 'PUT': - request = self._client.put(url, query_parameters) + request = self._client.put(url, query_parameters, header_parameters, body) elif method == 'POST': - request = self._client.post(url, query_parameters) + request = self._client.post(url, query_parameters, header_parameters, body) elif method == 'HEAD': - request = self._client.head(url, query_parameters) + request = self._client.head(url, query_parameters, header_parameters, body) elif method == 'PATCH': - request = self._client.patch(url, query_parameters) + request = self._client.patch(url, query_parameters, header_parameters, body) elif method == 'DELETE': - request = self._client.delete(url, query_parameters) + request = self._client.delete(url, query_parameters, header_parameters, body) elif method == 'MERGE': - request = self._client.merge(url, query_parameters) + request = self._client.merge(url, query_parameters, header_parameters, body) - response = self._client.send(request, header_parameters, body, **operation_config) + response = self._client.send_request(request, **operation_config) if response.status_code not in expected_status_codes: - exp = CloudError(response) - exp.request_id = response.headers.get('x-ms-request-id') + exp = SendRequestException(response, response.status_code) raise exp elif response.status_code == 202 and polling_timeout > 0: def get_long_running_output(response): return response poller = LROPoller(self._client, - ClientRawResponse(None, response), + PipelineResponse(None, response, None), get_long_running_output, ARMPolling(polling_interval, **operation_config)) response = self.get_poller_result(poller, polling_timeout) @@ -102,3 +101,9 @@ class GenericRestClient(object): return poller.result() except Exception as exc: raise + + +class SendRequestException(Exception): + def __init__(self, response, status_code): + self.response = response + self.status_code = status_code diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_account_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_account_info.py index 90e2799fe..5061604e2 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_account_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_account_info.py @@ -102,7 +102,6 @@ account_info: try: - from msrestazure.azure_exceptions import CloudError from azure.graphrbac import GraphRbacManagementClient from azure.graphrbac.models import GraphErrorException except ImportError: @@ -170,7 +169,7 @@ class AzureRMAccountInfo(AzureRMModuleBase): try: subscription_list_response = list(self.subscription_client.subscriptions.list()) - except CloudError as exc: + except Exception as exc: self.fail("Failed to list all subscriptions - {0}".format(str(exc))) results['id'] = subscription_list_response[0].subscription_id diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adapplication.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adapplication.py index f65f8b191..9f21728fc 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adapplication.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adapplication.py @@ -234,26 +234,26 @@ author: ''' EXAMPLES = ''' - - name: Create ad application - azure_rm_adapplication: - tenant: "{{ tenant_id }}" - display_name: "{{ display_name }}" - - - name: Create application with more parameter - azure_rm_adapplication: - tenant: "{{ tenant_id }}" - display_name: "{{ display_name }}" - available_to_other_tenants: False - credential_description: "for test" - end_date: 2021-10-01 - start_date: 2021-05-18 - identifier_uris: fredtest02.com - - - name: delete ad application - azure_rm_adapplication: - tenant: "{{ tenant_id }}" - app_id: "{{ app_id }}" - state: absent +- name: Create ad application + azure_rm_adapplication: + tenant: "{{ tenant_id }}" + display_name: "{{ display_name }}" + +- name: Create application with more parameter + azure_rm_adapplication: + tenant: "{{ tenant_id }}" + display_name: "{{ display_name }}" + available_to_other_tenants: false + credential_description: "for test" + end_date: 2021-10-01 + start_date: 2021-05-18 + identifier_uris: fredtest02.com + +- name: delete ad application + azure_rm_adapplication: + tenant: "{{ tenant_id }}" + app_id: "{{ app_id }}" + state: absent ''' RETURN = ''' @@ -322,7 +322,6 @@ output: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt try: - from msrestazure.azure_exceptions import CloudError from azure.graphrbac.models import GraphErrorException import datetime from dateutil.relativedelta import relativedelta diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adapplication_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adapplication_info.py index becfdd0b3..939058815 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adapplication_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adapplication_info.py @@ -48,21 +48,20 @@ author: ''' EXAMPLES = ''' - - name: get ad app info by App ID - azure_rm_adapplication_info: - app_id: "{{ app_id }}" - tenant: "{{ tenant_id }}" - - - name: get ad app info ---- by object ID - azure_rm_adapplication_info: - object_id: "{{ object_id }}" - tenant: "{{ tenant_id }}" - - - name: get ad app info ---- by identifier uri - azure_rm_adapplication_info: - identifier_uri: "{{ identifier_uri }}" - tenant: "{{ tenant_id }}" - +- name: get ad app info by App ID + azure_rm_adapplication_info: + app_id: "{{ app_id }}" + tenant: "{{ tenant_id }}" + +- name: get ad app info ---- by object ID + azure_rm_adapplication_info: + object_id: "{{ object_id }}" + tenant: "{{ tenant_id }}" + +- name: get ad app info ---- by identifier uri + azure_rm_adapplication_info: + identifier_uri: "{{ identifier_uri }}" + tenant: "{{ tenant_id }}" ''' RETURN = ''' @@ -101,7 +100,6 @@ applications: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBase try: - from msrestazure.azure_exceptions import CloudError from azure.graphrbac.models import GraphErrorException except ImportError: # This is handled in azure_rm_common diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adgroup.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adgroup.py index 092ed8c78..812b6953c 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adgroup.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adgroup.py @@ -74,100 +74,99 @@ author: ''' EXAMPLES = ''' - - name: Create Group - azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - display_name: "Group-Name" - mail_nickname: "Group-Mail-Nickname" - state: 'present' - - - name: Delete Group using display_name and mail_nickname - azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - display_name: "Group-Name" - mail_nickname: "Group-Mail-Nickname" - state: 'absent' - - - name: Delete Group using object_id - azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - state: 'absent' - - - name: Ensure Users are Members of a Group using display_name and mail_nickname - azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - display_name: "Group-Name" - mail_nickname: "Group-Mail-Nickname" - state: 'present' - present_members: - - "https://graph.windows.net/{{ tenant_id }}/directoryObjects/{{ ad_object_1_object_id }}" - - "https://graph.windows.net/{{ tenant_id }}/directoryObjects/{{ ad_object_2_object_id }}" - - - name: Ensure Users are Members of a Group using object_id - azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - state: 'present' - present_members: - - "https://graph.windows.net/{{ ad_object_1_tenant_id }}/directoryObjects/{{ ad_object_1_object_id }}" - - "https://graph.windows.net/{{ ad_object_2_tenant_id }}/directoryObjects/{{ ad_object_2_object_id }}" - - - name: Ensure Users are not Members of a Group using display_name and mail_nickname - azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - display_name: "Group-Name" - mail_nickname: "Group-Mail-Nickname" - state: 'present' - absent_members: - - "{{ ad_object_1_object_id }}" - - - name: Ensure Users are Members of a Group using object_id - azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - state: 'present' - absent_members: - - "{{ ad_object_1_object_id }}" - - - name: Ensure Users are Owners of a Group using display_name and mail_nickname - azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - display_name: "Group-Name" - mail_nickname: "Group-Mail-Nickname" - state: 'present' - present_owners: - - "https://graph.windows.net/{{ tenant_id }}/directoryObjects/{{ ad_object_1_object_id }}" - - "https://graph.windows.net/{{ tenant_id }}/directoryObjects/{{ ad_object_2_object_id }}" - - - name: Ensure Users are Owners of a Group using object_id - azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - state: 'present' - present_owners: - - "https://graph.windows.net/{{ ad_object_1_tenant_id }}/directoryObjects/{{ ad_object_1_object_id }}" - - "https://graph.windows.net/{{ ad_object_2_tenant_id }}/directoryObjects/{{ ad_object_2_object_id }}" - - - name: Ensure Users are not Owners of a Group using display_name and mail_nickname - azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - display_name: "Group-Name" - mail_nickname: "Group-Mail-Nickname" - state: 'present' - absent_owners: - - "{{ ad_object_1_object_id }}" - - "{{ ad_object_2_object_id }}" - - - name: Ensure Users are Owners of a Group using object_id - azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - state: 'present' - absent_owners: - - "{{ ad_object_1_object_id }}" - - "{{ ad_object_2_object_id }}" +- name: Create Group + azure_rm_adgroup: + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + display_name: "Group-Name" + mail_nickname: "Group-Mail-Nickname" + state: 'present' + +- name: Delete Group using display_name and mail_nickname + azure_rm_adgroup: + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + display_name: "Group-Name" + mail_nickname: "Group-Mail-Nickname" + state: 'absent' + +- name: Delete Group using object_id + azure_rm_adgroup: + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + state: 'absent' + +- name: Ensure Users are Members of a Group using display_name and mail_nickname + azure_rm_adgroup: + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + display_name: "Group-Name" + mail_nickname: "Group-Mail-Nickname" + state: 'present' + present_members: + - "https://graph.windows.net/{{ tenant_id }}/directoryObjects/{{ ad_object_1_object_id }}" + - "https://graph.windows.net/{{ tenant_id }}/directoryObjects/{{ ad_object_2_object_id }}" + +- name: Ensure Users are Members of a Group using object_id + azure_rm_adgroup: + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + state: 'present' + present_members: + - "https://graph.windows.net/{{ ad_object_1_tenant_id }}/directoryObjects/{{ ad_object_1_object_id }}" + - "https://graph.windows.net/{{ ad_object_2_tenant_id }}/directoryObjects/{{ ad_object_2_object_id }}" + +- name: Ensure Users are not Members of a Group using display_name and mail_nickname + azure_rm_adgroup: + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + display_name: "Group-Name" + mail_nickname: "Group-Mail-Nickname" + state: 'present' + absent_members: + - "{{ ad_object_1_object_id }}" +- name: Ensure Users are Members of a Group using object_id + azure_rm_adgroup: + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + state: 'present' + absent_members: + - "{{ ad_object_1_object_id }}" + +- name: Ensure Users are Owners of a Group using display_name and mail_nickname + azure_rm_adgroup: + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + display_name: "Group-Name" + mail_nickname: "Group-Mail-Nickname" + state: 'present' + present_owners: + - "https://graph.windows.net/{{ tenant_id }}/directoryObjects/{{ ad_object_1_object_id }}" + - "https://graph.windows.net/{{ tenant_id }}/directoryObjects/{{ ad_object_2_object_id }}" + +- name: Ensure Users are Owners of a Group using object_id + azure_rm_adgroup: + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + state: 'present' + present_owners: + - "https://graph.windows.net/{{ ad_object_1_tenant_id }}/directoryObjects/{{ ad_object_1_object_id }}" + - "https://graph.windows.net/{{ ad_object_2_tenant_id }}/directoryObjects/{{ ad_object_2_object_id }}" + +- name: Ensure Users are not Owners of a Group using display_name and mail_nickname + azure_rm_adgroup: + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + display_name: "Group-Name" + mail_nickname: "Group-Mail-Nickname" + state: 'present' + absent_owners: + - "{{ ad_object_1_object_id }}" + - "{{ ad_object_2_object_id }}" + +- name: Ensure Users are Owners of a Group using object_id + azure_rm_adgroup: + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + state: 'present' + absent_owners: + - "{{ ad_object_1_object_id }}" + - "{{ ad_object_2_object_id }}" ''' RETURN = ''' @@ -222,7 +221,6 @@ group_members: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBase try: - from msrestazure.azure_exceptions import CloudError from azure.graphrbac.models import GraphErrorException from azure.graphrbac.models import GroupCreateParameters except ImportError: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adgroup_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adgroup_info.py index 9e8c5e456..37bc1febb 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adgroup_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adgroup_info.py @@ -73,52 +73,51 @@ author: ''' EXAMPLES = ''' - - name: Return a specific group using object_id - azure_rm_adgroup_info: - object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - - - name: Return a specific group using object_id and return the owners of the group - azure_rm_adgroup_info: - object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - return_owners: True - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - - - name: Return a specific group using object_id and return the owners and members of the group - azure_rm_adgroup_info: - object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - return_owners: True - return_group_members: True - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - - - name: Return a specific group using object_id and return the groups the group is a member of - azure_rm_adgroup_info: - object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - return_member_groups: True - tenant: "{{ tenant_id }}" - - - name: Return a specific group using object_id and check an ID for membership - azure_rm_adgroup_info: - object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - check_membership: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - - - name: Return a specific group using displayName for attribute_name - azure_rm_adgroup_info: - attribute_name: "displayName" - attribute_value: "Display-Name-Of-AD-Group" - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - - - name: Return groups matching odata_filter - azure_rm_adgroup_info: - odata_filter: "mailNickname eq 'Mail-Nickname-Of-AD-Group'" - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - - - name: Return all groups - azure_rm_adgroup_info: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - all: True - +- name: Return a specific group using object_id + azure_rm_adgroup_info: + object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + +- name: Return a specific group using object_id and return the owners of the group + azure_rm_adgroup_info: + object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + return_owners: true + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + +- name: Return a specific group using object_id and return the owners and members of the group + azure_rm_adgroup_info: + object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + return_owners: true + return_group_members: true + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + +- name: Return a specific group using object_id and return the groups the group is a member of + azure_rm_adgroup_info: + object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + return_member_groups: true + tenant: "{{ tenant_id }}" + +- name: Return a specific group using object_id and check an ID for membership + azure_rm_adgroup_info: + object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + check_membership: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + +- name: Return a specific group using displayName for attribute_name + azure_rm_adgroup_info: + attribute_name: "displayName" + attribute_value: "Display-Name-Of-AD-Group" + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + +- name: Return groups matching odata_filter + azure_rm_adgroup_info: + odata_filter: "mailNickname eq 'Mail-Nickname-Of-AD-Group'" + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + +- name: Return all groups + azure_rm_adgroup_info: + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + all: true ''' RETURN = ''' @@ -173,7 +172,6 @@ group_members: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBase try: - from msrestazure.azure_exceptions import CloudError from azure.graphrbac.models import GraphErrorException from azure.graphrbac.models import CheckGroupMembershipParameters except ImportError: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adpassword.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adpassword.py index d56791864..587d842b5 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adpassword.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adpassword.py @@ -5,7 +5,6 @@ # 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 -import datetime __metaclass__ = type @@ -66,7 +65,6 @@ options: extends_documentation_fragment: - azure.azcollection.azure - - azure.azcollection.azure_tags author: haiyuan_zhang (@haiyuazhang) @@ -75,12 +73,12 @@ author: ''' EXAMPLES = ''' - - name: create ad password - azure_rm_adpassword: - app_id: "{{ app_id }}" - state: present - value: "$abc12345678" - tenant: "{{ tenant_id }}" +- name: create ad password + azure_rm_adpassword: + app_id: "{{ app_id }}" + state: present + value: "$abc12345678" + tenant: "{{ tenant_id }}" ''' RETURN = ''' @@ -90,7 +88,7 @@ end_date: - Default value is one year after current time. type: str returned: always - sample: 2021-06-28T06:00:32.637070+00:00 + sample: "2021-06-28T06:00:32.637070+00:00" key_id: description: - The password key ID @@ -103,15 +101,15 @@ start_date: - Default value is current time. type: str returned: always - sample: 2020-06-28T06:00:32.637070+00:00 + sample: "2020-06-28T06:00:32.637070+00:00" ''' from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase import uuid +import datetime try: - from msrestazure.azure_exceptions import CloudError from azure.graphrbac.models import GraphErrorException from azure.graphrbac.models import PasswordCredential from azure.graphrbac.models import ApplicationUpdateParameters diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adpassword_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adpassword_info.py index 8fc99cb7e..7c82b7b9f 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adpassword_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adpassword_info.py @@ -5,7 +5,6 @@ # 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 -import datetime __metaclass__ = type @@ -62,11 +61,11 @@ author: ''' EXAMPLES = ''' - - name: get ad password info - azure_rm_adpassword_info: - app_id: "{{ app_id }}" - tenant: "{{ tenant_id }}" - key_id: "{{ key_id }}" +- name: get ad password info + azure_rm_adpassword_info: + app_id: "{{ app_id }}" + tenant: "{{ tenant_id }}" + key_id: "{{ key_id }}" ''' RETURN = ''' @@ -86,9 +85,9 @@ passwords: description: - Date or datemtime after which credentials expire. - Default value is one year after current time. - type: datetime + type: str returned: always - sample: 2021-06-18T06:51:25.508304+00:00 + sample: "2021-06-18T06:51:25.508304+00:00" key_id: description: - The password key ID. @@ -99,19 +98,16 @@ passwords: description: - Date or datetime at which credentials become valid. - Default value is current time - type: datetime + type: str returned: always - sample: 2020-06-18T06:51:25.508304+00:00 + sample: "2020-06-18T06:51:25.508304+00:00" ''' from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: - from msrestazure.azure_exceptions import CloudError from azure.graphrbac.models import GraphErrorException - from azure.graphrbac.models import PasswordCredential - from azure.graphrbac.models import ApplicationUpdateParameters except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adserviceprincipal.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adserviceprincipal.py index ca5586e48..a7d3b39fd 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adserviceprincipal.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adserviceprincipal.py @@ -46,7 +46,6 @@ options: extends_documentation_fragment: - azure.azcollection.azure - - azure.azcollection.azure_tags author: haiyuan_zhang (@haiyuazhang) @@ -54,11 +53,11 @@ author: ''' EXAMPLES = ''' - - name: create ad sp - azure_rm_adserviceprincipal: - app_id: "{{ app_id }}" - state: present - tenant: "{{ tenant_id }}" +- name: create ad sp + azure_rm_adserviceprincipal: + app_id: "{{ app_id }}" + state: present + tenant: "{{ tenant_id }}" ''' RETURN = ''' @@ -92,12 +91,10 @@ object_id: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt try: from azure.graphrbac.models import ServicePrincipalCreateParameters - from azure.graphrbac.models import ServicePrincipalUpdateParameters except Exception: pass try: - from msrestazure.azure_exceptions import CloudError from azure.graphrbac.models import GraphErrorException except ImportError: # This is handled in azure_rm_common diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adserviceprincipal_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adserviceprincipal_info.py index 80e30b47f..db27ccae8 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adserviceprincipal_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adserviceprincipal_info.py @@ -42,11 +42,10 @@ author: ''' EXAMPLES = ''' - - name: get ad sp info - azure_rm_adserviceprincipal_info: - app_id: "{{ app_id }}" - tenant: "{{ tenant_id }}" - +- name: get ad sp info + azure_rm_adserviceprincipal_info: + app_id: "{{ app_id }}" + tenant: "{{ tenant_id }}" ''' RETURN = ''' @@ -81,7 +80,6 @@ object_id: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBase try: - from msrestazure.azure_exceptions import CloudError from azure.graphrbac.models import GraphErrorException except ImportError: # This is handled in azure_rm_common diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aduser.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aduser.py index 2bfa04aac..b41c5ae7e 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aduser.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aduser.py @@ -151,7 +151,6 @@ EXAMPLES = ''' user_principal_name: "{{ user_id }}" tenant: "{{ tenant_id }}" state: "absent" - ''' RETURN = ''' @@ -202,7 +201,6 @@ user_type: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBase try: - from msrestazure.azure_exceptions import CloudError from azure.graphrbac.models import UserUpdateParameters from azure.graphrbac.models import UserCreateParameters from azure.graphrbac.models import PasswordProfile diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aduser_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aduser_info.py index 36d27d547..85460e741 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aduser_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aduser_info.py @@ -71,37 +71,37 @@ author: ''' EXAMPLES = ''' - - name: Using user_principal_name - azure.azcollection.azure_rm_aduser_info: - user_principal_name: user@contoso.com - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - - - name: Using object_id - azure.azcollection.azure_rm_aduser_info: - object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - - - name: Using attribute mailNickname - not a collection - azure.azcollection.azure_rm_aduser_info: - attribute_name: mailNickname - attribute_value: users_mailNickname - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - - - name: Using attribute proxyAddresses - a collection - azure.azcollection.azure_rm_aduser_info: - attribute_name: proxyAddresses - attribute_value: SMTP:user@contoso.com - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - - - name: Using Filter mailNickname - azure.azcollection.azure_rm_aduser_info: - odata_filter: mailNickname eq 'user@contoso.com' - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - - - name: Using Filter proxyAddresses - azure.azcollection.azure_rm_aduser_info: - odata_filter: proxyAddresses/any(c:c eq 'SMTP:user@contoso.com') - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +- name: Using user_principal_name + azure.azcollection.azure_rm_aduser_info: + user_principal_name: user@contoso.com + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + +- name: Using object_id + azure.azcollection.azure_rm_aduser_info: + object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + +- name: Using attribute mailNickname - not a collection + azure.azcollection.azure_rm_aduser_info: + attribute_name: mailNickname + attribute_value: users_mailNickname + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + +- name: Using attribute proxyAddresses - a collection + azure.azcollection.azure_rm_aduser_info: + attribute_name: proxyAddresses + attribute_value: SMTP:user@contoso.com + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + +- name: Using Filter mailNickname + azure.azcollection.azure_rm_aduser_info: + odata_filter: mailNickname eq 'user@contoso.com' + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + +- name: Using Filter proxyAddresses + azure.azcollection.azure_rm_aduser_info: + odata_filter: proxyAddresses/any(c:c eq 'SMTP:user@contoso.com') + tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ''' RETURN = ''' @@ -152,7 +152,6 @@ user_type: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBase try: - from msrestazure.azure_exceptions import CloudError from azure.graphrbac.models import GraphErrorException except ImportError: # This is handled in azure_rm_common diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aks.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aks.py index 56e4fae2d..bb034b48b 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aks.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aks.py @@ -21,59 +21,74 @@ options: description: - Name of a resource group where the managed Azure Container Services (AKS) exists or will be created. required: true + type: str name: description: - Name of the managed Azure Container Services (AKS) instance. required: true + type: str state: description: - Assert the state of the AKS. Use C(present) to create or update an AKS and C(absent) to delete it. default: present + type: str choices: - absent - present location: description: - Valid azure location. Defaults to location of the resource group. + type: str dns_prefix: description: - DNS prefix specified when creating the managed cluster. + type: str kubernetes_version: description: - Version of Kubernetes specified when creating the managed cluster. + type: str linux_profile: description: - The Linux profile suboptions. - Optional, provide if you need an ssh access to the cluster nodes. + type: dict suboptions: admin_username: description: - The Admin Username for the cluster. required: true + type: str ssh_key: description: - The Public SSH Key used to access the cluster. required: true + type: str agent_pool_profiles: description: - The agent pool profile suboptions. + type: list + elements: dict suboptions: name: description: - Unique name of the agent pool profile in the context of the subscription and resource group. required: true + type: str count: description: - Number of agents (VMs) to host docker containers. - Allowed values must be in the range of C(1) to C(100) (inclusive). required: true + type: int vm_size: description: - The VM Size of each of the Agent Pool VM's (e.g. C(Standard_F1) / C(Standard_D2v2)). required: true + type: str os_disk_size_gb: description: - Size of the OS disk. + type: int enable_auto_scaling: description: - To enable auto-scaling. @@ -130,17 +145,43 @@ options: - 1 - 2 - 3 + os_type: + description: + - The operating system type. + type: str + choices: + - Linux + - Windows + storage_profiles: + description: + - Storage profile specifies what kind of storage used. + type: str + choices: + - StorageAccount + - ManagedDisks + ports: + description: + - List of the agent pool's port. + type: list + elements: int + dns_prefix: + description: + - DNS prefix specified when creating the managed cluster. + type: str service_principal: description: - The service principal suboptions. If not provided - use system-assigned managed identity. + type: dict suboptions: client_id: description: - The ID for the Service Principal. + type: str required: true client_secret: description: - The secret password associated with the service principal. + type: str enable_rbac: description: - Enable RBAC. @@ -150,6 +191,7 @@ options: network_profile: description: - Profile of network configuration. + type: dict suboptions: network_plugin: description: @@ -158,12 +200,13 @@ options: - With C(kubenet), nodes get an IP address from the Azure virtual network subnet. - AKS features such as Virtual Nodes or network policies aren't supported with C(kubenet). - C(azure) enables Azure Container Networking Interface(CNI), every pod gets an IP address from the subnet and can be accessed directly. - default: kubenet + type: str choices: - azure - kubenet network_policy: description: Network policy used for building Kubernetes network. + type: str choices: - azure - calico @@ -172,26 +215,27 @@ options: - A CIDR notation IP range from which to assign pod IPs when I(network_plugin=kubenet) is used. - It should be a large address space that isn't in use elsewhere in your network environment. - This address range must be large enough to accommodate the number of nodes that you expect to scale up to. - default: "10.244.0.0/16" + type: str service_cidr: description: - A CIDR notation IP range from which to assign service cluster IPs. - It must not overlap with any Subnet IP ranges. - It should be the *.10 address of your service IP address range. - default: "10.0.0.0/16" + type: str dns_service_ip: description: - An IP address assigned to the Kubernetes DNS service. - It must be within the Kubernetes service address range specified in serviceCidr. - default: "10.0.0.10" + type: str docker_bridge_cidr: description: - A CIDR notation IP range assigned to the Docker bridge network. - It must not overlap with any Subnet IP ranges or the Kubernetes service address range. - default: "172.17.0.1/16" + type: str load_balancer_sku: description: - The load balancer sku for the managed cluster. + type: str choices: - standard - basic @@ -199,12 +243,14 @@ options: description: - How outbound traffic will be configured for a cluster. type: str + default: loadBalancer choices: - loadBalancer - userDefinedRouting api_server_access_profile: description: - Profile of API Access configuration. + type: dict suboptions: authorized_ip_ranges: description: @@ -220,17 +266,22 @@ options: aad_profile: description: - Profile of Azure Active Directory configuration. + type: dict suboptions: client_app_id: description: The client AAD application ID. + type: str server_app_id: description: The server AAD application ID. + type: str server_app_secret: description: The server AAD application secret. + type: str tenant_id: description: - The AAD tenant ID to use for authentication. - If not specified, will use the tenant of the deployment subscription. + type: str managed: description: - Whether to enable manged AAD. @@ -252,39 +303,54 @@ options: description: - The HTTP application routing solution makes it easy to access applications that are deployed to your cluster. type: dict + aliases: + - httpApplicationRouting suboptions: enabled: description: - Whether the solution enabled. type: bool + default: true monitoring: description: - It gives you performance visibility by collecting memory and processor metrics from controllers, nodes, and containers that are available in Kubernetes through the Metrics API. type: dict + aliases: + - omsagent suboptions: enabled: description: - Whether the solution enabled. type: bool + default: true log_analytics_workspace_resource_id: description: - Where to store the container metrics. + type: str required: true + aliases: + - logAnalyticsWorkspaceResourceID virtual_node: description: - With virtual nodes, you have quick provisioning of pods, and only pay per second for their execution time. - You don't need to wait for Kubernetes cluster autoscaler to deploy VM compute nodes to run the additional pods. type: dict + aliases: + - aciConnector suboptions: enabled: description: - Whether the solution enabled. type: bool + default: true subnet_resource_id: description: - Subnet associated to the cluster. + type: str required: true + aliases: + - SubnetName node_resource_group: description: - Name of the resource group containing agent pool nodes. @@ -302,106 +368,106 @@ author: ''' EXAMPLES = ''' - - name: Create an AKS instance With A System Node Pool & A User Node Pool - azure_rm_aks: - name: myAKS - resource_group: myResourceGroup - location: eastus - dns_prefix: akstest - kubernetes_version: 1.14.6 - linux_profile: - admin_username: azureuser - ssh_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAA... - service_principal: - client_id: "cf72ca99-f6b9-4004-b0e0-bee10c521948" - client_secret: "Password1234!" - agent_pool_profiles: - - name: default - count: 1 - vm_size: Standard_B2s - enable_auto_scaling: True - type: VirtualMachineScaleSets - mode: System - max_count: 3 - min_count: 1 - enable_rbac: yes - - name: user - count: 1 - vm_size: Standard_D2_v2 - enable_auto_scaling: True - type: VirtualMachineScaleSets - mode: User - max_count: 3 - min_count: 1 - enable_rbac: yes - - - name: Create a managed Azure Container Services (AKS) instance - azure_rm_aks: - name: myAKS - location: eastus - resource_group: myResourceGroup - dns_prefix: akstest - kubernetes_version: 1.14.6 - linux_profile: - admin_username: azureuser - ssh_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAA... - service_principal: - client_id: "cf72ca99-f6b9-4004-b0e0-bee10c521948" - client_secret: "Password123!" - agent_pool_profiles: - - name: default - count: 5 - mode: System - vm_size: Standard_B2s - tags: - Environment: Production - - - name: Use minimal parameters and system-assigned identity - azure_rm_aks: - name: myMinimalCluster - location: eastus - resource_group: myExistingResourceGroup - dns_prefix: akstest - agent_pool_profiles: - - name: default - count: 1 - vm_size: Standard_D2_v2 - - - name: Create AKS with userDefinedRouting "Link:https://docs.microsoft.com/en-us/azure/aks/limit-egress-traffic#add-a-dnat-rule-to-azure-firewall" - azure_rm_aks: - name: "minimal{{ rpfx }}" - location: eastus - resource_group: "{{ resource_group }}" - kubernetes_version: "{{ versions.azure_aks_versions[0] }}" - dns_prefix: "aks{{ rpfx }}" - service_principal: - client_id: "{{ client_id }}" - client_secret: "{{ client_secret }}" - network_profile: - network_plugin: azure - load_balancer_sku: standard - outbound_type: userDefinedRouting - service_cidr: "10.41.0.0/16" - dns_service_ip: "10.41.0.10" - docker_bridge_cidr: "172.17.0.1/16" - api_server_access_profile: - authorized_ip_ranges: - - "20.106.246.252/32" - enable_private_cluster: no - agent_pool_profiles: - - name: default - count: 1 - vm_size: Standard_B2s - mode: System - vnet_subnet_id: "{{ output.subnets[0].id }}" - type: VirtualMachineScaleSets - enable_auto_scaling: false - - - name: Remove a managed Azure Container Services (AKS) instance - azure_rm_aks: - name: myAKS - resource_group: myResourceGroup - state: absent +- name: Create an AKS instance With A System Node Pool & A User Node Pool + azure_rm_aks: + name: myAKS + resource_group: myResourceGroup + location: eastus + dns_prefix: akstest + kubernetes_version: 1.14.6 + linux_profile: + admin_username: azureuser + ssh_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAA... + service_principal: + client_id: "cf72ca99-f6b9-4004-b0e0-bee10c521948" + client_secret: "Password1234!" + agent_pool_profiles: + - name: default + count: 1 + vm_size: Standard_B2s + enable_auto_scaling: true + type: VirtualMachineScaleSets + mode: System + max_count: 3 + min_count: 1 + enable_rbac: true + - name: user + count: 1 + vm_size: Standard_D2_v2 + enable_auto_scaling: true + type: VirtualMachineScaleSets + mode: User + max_count: 3 + min_count: 1 + enable_rbac: true + +- name: Create a managed Azure Container Services (AKS) instance + azure_rm_aks: + name: myAKS + location: eastus + resource_group: myResourceGroup + dns_prefix: akstest + kubernetes_version: 1.14.6 + linux_profile: + admin_username: azureuser + ssh_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAA... + service_principal: + client_id: "cf72ca99-f6b9-4004-b0e0-bee10c521948" + client_secret: "Password123!" + agent_pool_profiles: + - name: default + count: 5 + mode: System + vm_size: Standard_B2s + tags: + Environment: Production + +- name: Use minimal parameters and system-assigned identity + azure_rm_aks: + name: myMinimalCluster + location: eastus + resource_group: myExistingResourceGroup + dns_prefix: akstest + agent_pool_profiles: + - name: default + count: 1 + vm_size: Standard_D2_v2 + +- name: Create AKS with userDefinedRouting "Link:https://docs.microsoft.com/en-us/azure/aks/limit-egress-traffic#add-a-dnat-rule-to-azure-firewall" + azure_rm_aks: + name: "minimal{{ rpfx }}" + location: eastus + resource_group: "{{ resource_group }}" + kubernetes_version: "{{ versions.azure_aks_versions[0] }}" + dns_prefix: "aks{{ rpfx }}" + service_principal: + client_id: "{{ client_id }}" + client_secret: "{{ client_secret }}" + network_profile: + network_plugin: azure + load_balancer_sku: standard + outbound_type: userDefinedRouting + service_cidr: "10.41.0.0/16" + dns_service_ip: "10.41.0.10" + docker_bridge_cidr: "172.17.0.1/16" + api_server_access_profile: + authorized_ip_ranges: + - "20.106.246.252/32" + enable_private_cluster: false + agent_pool_profiles: + - name: default + count: 1 + vm_size: Standard_B2s + mode: System + vnet_subnet_id: "{{ output.subnets[0].id }}" + type: VirtualMachineScaleSets + enable_auto_scaling: false + +- name: Remove a managed Azure Container Services (AKS) instance + azure_rm_aks: + name: myAKS + resource_group: myResourceGroup + state: absent ''' RETURN = ''' state: @@ -611,8 +677,8 @@ agent_pool_profile_spec = dict( availability_zones=dict(type='list', elements='int', choices=[1, 2, 3]), os_type=dict(type='str', choices=['Linux', 'Windows']), orchestrator_version=dict(type='str', required=False), - type=dict(type='str', choice=['VirtualMachineScaleSets', 'AvailabilitySet']), - mode=dict(type='str', choice=['System', 'User']), + type=dict(type='str', choices=['VirtualMachineScaleSets', 'AvailabilitySet']), + mode=dict(type='str', choices=['System', 'User']), enable_auto_scaling=dict(type='bool'), max_count=dict(type='int'), node_labels=dict(type='dict'), @@ -623,12 +689,12 @@ agent_pool_profile_spec = dict( network_profile_spec = dict( network_plugin=dict(type='str', choices=['azure', 'kubenet']), - network_policy=dict(type='str'), + network_policy=dict(type='str', choices=['azure', 'calico']), pod_cidr=dict(type='str'), service_cidr=dict(type='str'), dns_service_ip=dict(type='str'), docker_bridge_cidr=dict(type='str'), - load_balancer_sku=dict(type='str'), + load_balancer_sku=dict(type='str', choices=['standard', 'basic']), outbound_type=dict(type='str', default='loadBalancer', choices=['userDefinedRouting', 'loadBalancer']) ) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aks_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aks_info.py index 19e802833..c97bd893e 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aks_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aks_info.py @@ -23,9 +23,11 @@ options: name: description: - Limit results to a specific resource group. + type: str resource_group: description: - The resource group to search for the desired Azure Kubernetes Service + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -35,6 +37,7 @@ options: description: - Show kubeconfig of the AKS cluster. - Note the operation will cost more network overhead, not recommended when listing AKS. + type: str choices: - user - admin @@ -47,18 +50,18 @@ author: ''' EXAMPLES = ''' - - name: Get facts for one Azure Kubernetes Service - azure_rm_aks_info: - name: Testing - resource_group: myResourceGroup - - - name: Get facts for all Azure Kubernetes Services - azure_rm_aks_info: - - - name: Get facts by tags - azure_rm_aks_info: - tags: - - testing +- name: Get facts for one Azure Kubernetes Service + azure_rm_aks_info: + name: Testing + resource_group: myResourceGroup + +- name: Get facts for all Azure Kubernetes Services + azure_rm_aks_info: + +- name: Get facts by tags + azure_rm_aks_info: + tags: + - testing ''' RETURN = ''' @@ -118,10 +121,12 @@ class AzureRMManagedClusterInfo(AzureRMModuleBase): for key in self.module_args: setattr(self, key, kwargs[key]) - self.results['aks'] = ( - self.get_item() if self.name - else self.list_items() - ) + if self.name is not None and self.resource_group is not None: + self.results['aks'] = self.get_item() + elif self.resource_group is not None: + self.results['aks'] = self.list_by_resourcegroup() + else: + self.results['aks'] = self.list_items() return self.results @@ -145,13 +150,33 @@ class AzureRMManagedClusterInfo(AzureRMModuleBase): return result + def list_by_resourcegroup(self): + """Get all Azure Kubernetes Services""" + + self.log('List all Azure Kubernetes Services under resource group') + + try: + response = self.managedcluster_client.managed_clusters.list_by_resource_group(self.resource_group) + 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): + item_dict = self.serialize_obj(item, AZURE_OBJECT_CLASS) + if self.show_kubeconfig: + item_dict['kube_config'] = self.get_aks_kubeconfig(self.resource_group, item.name) + results.append(item_dict) + + return results + def list_items(self): """Get all Azure Kubernetes Services""" self.log('List all Azure Kubernetes Services') try: - response = self.managedcluster_client.managed_clusters.list(self.resource_group) + response = self.managedcluster_client.managed_clusters.list() except Exception as exc: self.fail('Failed to list all items - {0}'.format(str(exc))) @@ -160,7 +185,7 @@ class AzureRMManagedClusterInfo(AzureRMModuleBase): if self.has_tags(item.tags, self.tags): item_dict = self.serialize_obj(item, AZURE_OBJECT_CLASS) if self.show_kubeconfig: - item_dict['kube_config'] = self.get_aks_kubeconfig(self.resource_group, item.name) + item_dict['kube_config'] = self.get_aks_kubeconfig(item.resource_group, item.name) results.append(item_dict) return results diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksagentpool.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksagentpool.py index b578826f6..f84362e95 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksagentpool.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksagentpool.py @@ -500,7 +500,7 @@ class AzureRMAksAgentPool(AzureRMModuleBase): mode=agent_pool.mode, orchestrator_version=agent_pool.orchestrator_version, node_image_version=agent_pool.node_image_version, - upgrade_settings=agent_pool.upgrade_settings, + upgrade_settings=dict(), provisioning_state=agent_pool.provisioning_state, availability_zones=[], enable_node_public_ip=agent_pool.enable_node_public_ip, @@ -511,6 +511,9 @@ class AzureRMAksAgentPool(AzureRMModuleBase): node_taints=agent_pool.node_taints, ) + if agent_pool.upgrade_settings is not None: + agent_pool_dict['upgrade_settings']['max_surge'] = agent_pool.upgrade_settings.max_surge + if agent_pool.availability_zones is not None: for key in agent_pool.availability_zones: agent_pool_dict['availability_zones'].append(int(key)) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksagentpool_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksagentpool_info.py index 977261da8..59f3b696d 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksagentpool_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksagentpool_info.py @@ -41,17 +41,16 @@ author: ''' EXAMPLES = ''' - - name: Get node agent pool by cluster name - azure_rm_aksagentpool_info: - resource_group: myRG - cluster_name: testcluster - - - name: Get node agent pool by name - azure_rm_aksagentpool_info: - resource_group: myRG - cluster_name: testcluster - name: default +- name: Get node agent pool by cluster name + azure_rm_aksagentpool_info: + resource_group: myRG + cluster_name: testcluster +- name: Get node agent pool by name + azure_rm_aksagentpool_info: + resource_group: myRG + cluster_name: testcluster + name: default ''' RETURN = ''' @@ -310,7 +309,7 @@ class AzureRMAgentPoolInfo(AzureRMModuleBase): availability_zones=[], orchestrator_version=agent_pool.orchestrator_version, node_image_version=agent_pool.node_image_version, - upgrade_settings=agent_pool.upgrade_settings, + upgrade_settings=dict(), provisioning_state=agent_pool.provisioning_state, enable_node_public_ip=agent_pool.enable_node_public_ip, scale_set_priority=agent_pool.scale_set_priority, @@ -320,6 +319,9 @@ class AzureRMAgentPoolInfo(AzureRMModuleBase): node_taints=agent_pool.node_taints, ) + if agent_pool.upgrade_settings is not None: + agent_pool_dict['upgrade_settings']['max_surge'] = agent_pool.upgrade_settings.max_surge + if agent_pool.availability_zones is not None: for key in agent_pool.availability_zones: agent_pool_dict['availability_zones'].append(int(key)) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksagentpoolversion_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksagentpoolversion_info.py index 33cf24317..790e8d278 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksagentpoolversion_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksagentpoolversion_info.py @@ -40,10 +40,10 @@ author: ''' EXAMPLES = ''' - - name: Get available versions an AKS can be upgrade to - azure_rm_aksagentpoolversion_info: - resource_group: myResourceGroup - cluster_name: myAKSName +- name: Get available versions an AKS can be upgrade to + azure_rm_aksagentpoolversion_info: + resource_group: myResourceGroup + cluster_name: myAKSName ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksupgrade_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksupgrade_info.py index ae17906a2..b4a40f86a 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksupgrade_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksupgrade_info.py @@ -39,11 +39,11 @@ author: ''' EXAMPLES = ''' - - name: Get available upgrade versions for AKS instance - azure_rm_aksupgrade_info: - name: myAKS - resource_group: myResourceGroup - register: myAKSupgrades +- name: Get available upgrade versions for AKS instance + azure_rm_aksupgrade_info: + name: myAKS + resource_group: myResourceGroup + register: myAKSupgrades ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksversion_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksversion_info.py index 4306fcce8..9e5af42ce 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksversion_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksversion_info.py @@ -24,9 +24,11 @@ options: description: - Get the versions available for creating a managed Kubernetes cluster. required: true + type: str version: description: - Get the upgrade versions available for a managed Kubernetes cluster version. + type: str extends_documentation_fragment: - azure.azcollection.azure @@ -36,13 +38,13 @@ author: ''' EXAMPLES = ''' - - name: Get available versions for AKS in location eastus - azure_rm_aksversion_info: - location: eastus - - name: Get available versions an AKS can be upgrade to - azure_rm_aksversion_info: - location: eastis - version: 1.11.6 +- name: Get available versions for AKS in location eastus + azure_rm_aksversion_info: + location: eastus +- name: Get available versions an AKS can be upgrade to + azure_rm_aksversion_info: + location: eastis + version: 1.11.6 ''' RETURN = ''' @@ -54,13 +56,6 @@ azure_aks_versions: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase -try: - from msrestazure.azure_exceptions import CloudError - from azure.common import AzureHttpError -except Exception: - # handled in azure_rm_common - pass - class AzureRMAKSVersion(AzureRMModuleBase): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagement.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagement.py index 221bd44b9..97a7868d1 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagement.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagement.py @@ -243,33 +243,33 @@ author: ''' EXAMPLES = ''' - - name: Create a new API instance - azure_rm_apimanagement: - resource_group: 'myResourceGroup' - service_name: myService - api_id: testApi - description: testDescription - display_name: TestAPI - service_url: 'http://testapi.example.net/api' - path: myapiPath - protocols: - - https - - name: Update an existing API instance. - azure_rm_apimanagement: - resource_group: myResourceGroup - service_name: myService - api_id: testApi - display_name: newTestAPI - service_url: 'http://testapi.example.net/api' - path: myapiPath - protocols: - - https - - name: ApiManagementDeleteApi - azure_rm_apimanagement: - resource_group: myResourceGroup - service_name: myService - api_id: testApi - state: absent +- name: Create a new API instance + azure_rm_apimanagement: + resource_group: 'myResourceGroup' + service_name: myService + api_id: testApi + description: testDescription + display_name: TestAPI + service_url: 'http://testapi.example.net/api' + path: myapiPath + protocols: + - https +- name: Update an existing API instance. + azure_rm_apimanagement: + resource_group: myResourceGroup + service_name: myService + api_id: testApi + display_name: newTestAPI + service_url: 'http://testapi.example.net/api' + path: myapiPath + protocols: + - https +- name: ApiManagementDeleteApi + azure_rm_apimanagement: + resource_group: myResourceGroup + service_name: myService + api_id: testApi + state: absent ''' RETURN = \ @@ -284,15 +284,7 @@ id: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_rest import GenericRestClient from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt -from copy import deepcopy -import time import json -import re -try: - from msrestazure.azure_exceptions import CloudError -except ImportError: - # This is handled in azure_rm_common - pass class Actions: @@ -544,6 +536,7 @@ class AzureApiManagement(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) old_response = self.get_resource() @@ -609,13 +602,13 @@ class AzureApiManagement(AzureRMModuleBaseExt): 600, 30, ) - except CloudError as exc: + except Exception as exc: self.log('Error while creating/updating the Api instance.') self.fail('Error creating the Api instance: {0}'.format(str(exc))) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: - response = {'text': response.text} + response = {'text': response.context['deserialized_data']} return response @@ -633,7 +626,7 @@ class AzureApiManagement(AzureRMModuleBaseExt): 30, ) isDeleted = True - except CloudError as e: + except Exception as e: self.log('Error attempting to delete the Api instance.') self.fail('Error deleting the Api instance: {0}'.format(str(e))) @@ -653,9 +646,9 @@ class AzureApiManagement(AzureRMModuleBaseExt): 30, ) isFound = True - response = json.loads(response.text) + response = json.loads(response.body()) self.log("Response : {0}".format(response)) - except CloudError as e: + except Exception as e: self.log('Could not find the Api instance from the given parameters.') if isFound is True: return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagement_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagement_info.py index d223ede2e..30120b5e5 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagement_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagement_info.py @@ -48,15 +48,15 @@ author: ''' EXAMPLES = ''' - - name: Get the information of api - azure_rm_apimanagement_info: - resource_group: myResourceGroup - service_name: myService - - name: Get the information of api - azure_rm_apimanagement_info: - resource_group: myResourceGroup - service_name: myService - api_id: testApi +- name: Get the information of api + azure_rm_apimanagement_info: + resource_group: myResourceGroup + service_name: myService +- name: Get the information of api + azure_rm_apimanagement_info: + resource_group: myResourceGroup + service_name: myService + api_id: testApi ''' RETURN = ''' @@ -100,15 +100,7 @@ api: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_rest import GenericRestClient from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt -from copy import deepcopy -import time import json -import re -try: - from msrestazure.azure_exceptions import CloudError -except ImportError: - # This is handled in azure_rm_common - pass class AzureApiManagementInfo(AzureRMModuleBaseExt): @@ -163,6 +155,7 @@ class AzureApiManagementInfo(AzureRMModuleBaseExt): self.body[key] = kwargs[key] self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if (self.resource_group is not None and @@ -210,10 +203,10 @@ class AzureApiManagementInfo(AzureRMModuleBaseExt): 600, 30, ) - except CloudError as e: + except Exception as e: self.log('Could not get the information.{0}'.format(e)) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: return None @@ -233,10 +226,10 @@ class AzureApiManagementInfo(AzureRMModuleBaseExt): 600, 30, ) - except CloudError as e: + except Exception as e: self.log('Could not get info for the given api tags {0}'.format(e)) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: return None @@ -256,8 +249,8 @@ class AzureApiManagementInfo(AzureRMModuleBaseExt): 600, 30, ) - response = json.loads(response.text) - except CloudError as e: + response = json.loads(response.body()) + except Exception as e: self.log('Could not get info for a given services.{0}'.format(e)) try: response = json.loads(response.text) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagementservice.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagementservice.py index 0c2860191..8c694bec4 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagementservice.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagementservice.py @@ -100,15 +100,8 @@ id: import time import json -import re from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_rest import GenericRestClient from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt -from copy import deepcopy -try: - from msrestazure.azure_exceptions import CloudError -except ImportError: - # This is handled in azure_rm_common - pass class Actions: @@ -197,6 +190,7 @@ class AzureRMApiManagementService(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) resource_group = self.get_resource_group(self.resource_group) @@ -286,14 +280,14 @@ class AzureRMApiManagementService(AzureRMModuleBaseExt): self.status_code, 600, 30) - except CloudError as exc: + except Exception as exc: self.log('Error attempting to create the ApiManagementService instance.') self.fail('Error creating the ApiManagementService instance: {0}'.format(str(exc))) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: - response = {'text': response.text} + response = {'text': response.context['deserialized_data']} pass return response @@ -309,7 +303,7 @@ class AzureRMApiManagementService(AzureRMModuleBaseExt): self.status_code, 600, 30) - except CloudError as e: + except Exception as e: self.log('Error attempting to delete the ApiManagementService instance.') self.fail('Error deleting the ApiManagementService instance: {0}'.format(str(e))) @@ -329,10 +323,10 @@ class AzureRMApiManagementService(AzureRMModuleBaseExt): 30) found = True self.log("Response : {0}".format(response)) - except CloudError as e: + except Exception as e: self.log('Did not find the ApiManagementService instance.') if found is True: - return json.loads(response.text) + return json.loads(response.body()) return False diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagementservice_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagementservice_info.py index 72891fe14..663e87e78 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagementservice_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagementservice_info.py @@ -117,16 +117,9 @@ api_management_service: sample: null ''' -import time import json from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_rest import GenericRestClient from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt -from copy import deepcopy -try: - from msrestazure.azure_exceptions import CloudError -except ImportError: - # This is handled in azure_rm_common - pass class AzureRMApiManagementServiceInfo(AzureRMModuleBaseExt): @@ -163,6 +156,7 @@ class AzureRMApiManagementServiceInfo(AzureRMModuleBaseExt): setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if (self.resource_group is not None and self.name is not None): @@ -197,8 +191,8 @@ class AzureRMApiManagementServiceInfo(AzureRMModuleBaseExt): self.status_code, 600, 30) - results = json.loads(response.text) - except CloudError as e: + results = json.loads(response.body()) + except Exception as e: self.log('Could not get info for @(Model.ModuleOperationNameUpper).') return self.format_item(results) @@ -226,8 +220,8 @@ class AzureRMApiManagementServiceInfo(AzureRMModuleBaseExt): self.status_code, 600, 30) - results = json.loads(response.text) - except CloudError as e: + results = json.loads(response.body()) + except Exception as e: self.log('Could not get info for @(Model.ModuleOperationNameUpper).') return [self.format_item(x) for x in results['value']] if results['value'] else [] @@ -252,8 +246,8 @@ class AzureRMApiManagementServiceInfo(AzureRMModuleBaseExt): self.status_code, 600, 30) - results = json.loads(response.text) - except CloudError as e: + results = json.loads(response.body()) + except Exception as e: self.log('Could not get info for @(Model.ModuleOperationNameUpper).') return [self.format_item(x) for x in results['value']] if results['value'] else [] diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appgateway.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appgateway.py index 01f3b2eb5..f95766fa9 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appgateway.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appgateway.py @@ -21,13 +21,16 @@ options: description: - The name of the resource group. required: True + type: str name: description: - The name of the application gateway. required: True + type: str location: description: - Resource location. If not set, location from the resource group will be used as default. + type: str sku: description: - SKU of the application gateway resource. @@ -36,6 +39,7 @@ options: name: description: - Name of an application gateway SKU. + type: str choices: - 'standard_small' - 'standard_medium' @@ -47,6 +51,7 @@ options: tier: description: - Tier of an application gateway. + type: str choices: - 'standard' - 'standard_v2' @@ -55,6 +60,7 @@ options: capacity: description: - Capacity (instance count) of an application gateway. + type: int ssl_policy: description: - SSL policy of the application gateway resource. @@ -72,12 +78,14 @@ options: policy_type: description: - Type of SSL Policy. + type: str choices: - 'predefined' - 'custom' policy_name: description: - Name of Ssl C(predefined) policy. + type: str choices: - 'ssl_policy20150501' - 'ssl_policy20170401' @@ -119,6 +127,7 @@ options: min_protocol_version: description: - Minimum version of SSL protocol to be supported on application gateway. + type: str choices: - 'tls_v1_0' - 'tls_v1_1' @@ -137,15 +146,19 @@ options: id: description: - Full ID of the subnet resource. Required if I(name) and I(virtual_network_name) are not provided. + type: str name: description: - Name of the subnet. Only used if I(virtual_network_name) is also provided. + type: str virtual_network_name: description: - Name of the virtual network. Only used if I(name) is also provided. + type: str name: description: - Name of the resource that is unique within a resource group. This name can be used to access the resource. + type: str authentication_certificates: description: - Authentication certificates of the application gateway resource. @@ -155,9 +168,11 @@ options: data: description: - Certificate public data - base64 encoded pfx. + type: str name: description: - Name of the resource that is unique within a resource group. This name can be used to access the resource. + type: str redirect_configurations: description: - Redirect configurations of the application gateway resource. @@ -167,6 +182,7 @@ options: redirect_type: description: - Redirection type. + type: str choices: - 'permanent' - 'found' @@ -175,13 +191,18 @@ options: target_listener: description: - Reference to a listener to redirect the request to. + type: str request_routing_rules: description: - List of c(basic) request routing rule names within the application gateway to which the redirect is bound. version_added: "1.10.0" + type: list + elements: str url_path_maps: description: - List of URL path map names (c(path_based_routing) rules) within the application gateway to which the redirect is bound. + type: list + elements: str version_added: "1.10.0" path_rules: description: @@ -192,19 +213,24 @@ options: name: description: - Name of the URL rule. + type: str path_map_name: description: - Name of URL path map. + type: str version_added: "1.10.0" include_path: description: - Include path in the redirected url. + type: bool include_query_string: description: - Include query string in the redirected url. + type: bool name: description: - Name of the resource that is unique within a resource group. + type: str rewrite_rule_sets: description: - List of rewrite configurations for the application gateway resource. @@ -215,6 +241,7 @@ options: name: description: - Name of the rewrite rule set. + type: str required: True rewrite_rules: description: @@ -227,23 +254,28 @@ options: description: - Name of the rewrite rule. required: True + type: str rule_sequence: description: - Sequence of the rule that determines the order of execution within the set. required: True + type: int conditions: description: - Conditions based on which the action set execution will be evaluated. type: list elements: dict + default: [] suboptions: variable: description: - The parameter for the condition. + type: str required: True pattern: description: - The pattern, either fixed string or regular expression, that evaluates the truthfulness of the condition. + type: str required: True ignore_case: description: @@ -266,29 +298,37 @@ options: - List of actions to be taken on request headers. type: list elements: dict + default: [] suboptions: header_name: description: - Name of the header. + type: str required: True header_value: description: - Value of the header. - Leave the parameter unset to remove the header. + type: str + default: '' response_header_configurations: description: - List of actions to be taken on response headers. type: list elements: dict + default: [] suboptions: header_name: description: - Name of the header. + type: str required: True header_value: description: - Value of the header. - Leave the parameter unset to remove the header. + type: str + default: '' url_configuration: description: - Action to be taken on the URL. @@ -298,10 +338,12 @@ options: description: - Value to which the URL path will be rewriten. - Leave parameter unset to keep the original URL path. + type: str modified_query_string: description: - Value to which the URL query string will be rewriten. - Leave parameter unset to keep the original URL query string. + type: str reroute: description: - If set to true, will re-evaluate the path map provided in path-based request routing rules using modified path. @@ -317,13 +359,16 @@ options: description: - Base-64 encoded pfx certificate. - Only applicable in PUT Request. + type: str password: description: - Password for the pfx file specified in I(data). - Only applicable in PUT request. + type: str name: description: - Name of the resource that is unique within a resource group. This name can be used to access the resource. + type: str trusted_root_certificates: version_added: "1.15.0" description: @@ -342,6 +387,7 @@ options: key_vault_secret_id: description: - Secret Id of (base-64 encoded unencrypted pfx) 'Secret' or 'Certificate' object stored in KeyVault. + default: '' type: str frontend_ip_configurations: description: @@ -352,9 +398,11 @@ options: private_ip_address: description: - PrivateIPAddress of the network interface IP Configuration. + type: str private_ip_allocation_method: description: - PrivateIP allocation method. + type: str choices: - 'static' - 'dynamic' @@ -366,18 +414,23 @@ options: id: description: - Full ID of the subnet resource. Required if I(name) and I(virtual_network_name) are not provided. + type: str name: description: - Name of the subnet. Only used if I(virtual_network_name) is also provided. + type: str virtual_network_name: description: - Name of the virtual network. Only used if I(name) is also provided. + type: str public_ip_address: description: - Reference of the PublicIP resource. + type: raw name: description: - Name of the resource that is unique within a resource group. This name can be used to access the resource. + type: str frontend_ports: description: - List of frontend ports of the application gateway resource. @@ -387,9 +440,11 @@ options: port: description: - Frontend port. + type: str name: description: - Name of the resource that is unique within a resource group. This name can be used to access the resource. + type: str backend_address_pools: description: - List of backend address pool of the application gateway resource. @@ -405,12 +460,15 @@ options: fqdn: description: - Fully qualified domain name (FQDN). + type: str ip_address: description: - IP address. + type: str name: description: - Resource that is unique within a resource group. This name can be used to access the resource. + type: str probes: description: - Probes available to the application gateway resource. @@ -420,35 +478,42 @@ options: name: description: - Name of the I(probe) that is unique within an Application Gateway. + type: str protocol: description: - The protocol used for the I(probe). + type: str choices: - 'http' - 'https' host: description: - Host name to send the I(probe) to. + type: str path: description: - Relative path of I(probe). - Valid path starts from '/'. - Probe is sent to <Protocol>://<host>:<port><path>. + type: str timeout: description: - The probe timeout in seconds. - Probe marked as failed if valid response is not received with this timeout period. - Acceptable values are from 1 second to 86400 seconds. + type: int interval: description: - The probing interval in seconds. - This is the time interval between two consecutive probes. - Acceptable values are from 1 second to 86400 seconds. + type: int unhealthy_threshold: description: - The I(probe) retry count. - Backend server is marked down after consecutive probe failure count reaches UnhealthyThreshold. - Acceptable values are from 1 second to 20. + type: int pick_host_name_from_backend_http_settings: description: - Whether host header should be picked from the host name of the backend HTTP settings. Default value is false. @@ -463,18 +528,22 @@ options: probe: description: - Probe resource of an application gateway. + type: raw port: description: - The destination port on the backend. + type: int protocol: description: - The protocol used to communicate with the backend. + type: str choices: - 'http' - 'https' cookie_based_affinity: description: - Cookie based affinity. + type: str choices: - 'enabled' - 'disabled' @@ -497,6 +566,7 @@ options: - Request timeout in seconds. - Application Gateway will fail the request if response is not received within RequestTimeout. - Acceptable values are from 1 second to 86400 seconds. + type: int authentication_certificates: description: - List of references to application gateway authentication certificates. @@ -507,29 +577,35 @@ options: id: description: - Resource ID. + type: str trusted_root_certificates: version_added: "1.15.0" description: - Array of references to application gateway trusted root certificates. - Can be the name of the trusted root certificate or full resource ID. type: list - elements: str + elements: raw host_name: description: - Host header to be sent to the backend servers. + type: str pick_host_name_from_backend_address: description: - Whether host header should be picked from the host name of the backend server. Default value is false. + type: bool affinity_cookie_name: description: - Cookie name to use for the affinity cookie. + type: str path: description: - Path which should be used as a prefix for all C(http) requests. - Null means no path will be prefixed. Default value is null. + type: str name: description: - Name of the resource that is unique within a resource group. This name can be used to access the resource. + type: str http_listeners: description: - List of HTTP listeners of the application gateway resource. @@ -539,27 +615,34 @@ options: frontend_ip_configuration: description: - Frontend IP configuration resource of an application gateway. + type: raw frontend_port: description: - Frontend port resource of an application gateway. + type: raw protocol: description: - Protocol of the C(http) listener. + type: str choices: - 'http' - 'https' host_name: description: - Host name of C(http) listener. + type: str ssl_certificate: description: - SSL certificate resource of an application gateway. + type: raw require_server_name_indication: description: - Applicable only if I(protocol) is C(https). Enables SNI for multi-hosting. + type: bool name: description: - Name of the resource that is unique within a resource group. This name can be used to access the resource. + type: str url_path_maps: description: - List of URL path maps of the application gateway resource. @@ -569,18 +652,22 @@ options: name: description: - Name of the resource that is unique within the application gateway. This name can be used to access the resource. + type: str default_backend_address_pool: description: - Backend address pool resource of the application gateway which will be used if no path matches occur. - Mutually exclusive with I(default_redirect_configuration). + type: str default_backend_http_settings: description: - Backend http settings resource of the application gateway; used with I(default_backend_address_pool). + type: str default_rewrite_rule_set: description: - Default rewrite rule set for the path map. - Can be the name of the rewrite rule set or full resource ID. version_added: "1.11.0" + type: str path_rules: description: - List of URL path rules. @@ -590,22 +677,27 @@ options: name: description: - Name of the resource that is unique within the path map. + type: str backend_address_pool: description: - Backend address pool resource of the application gateway which will be used if the path is matched. - Mutually exclusive with I(redirect_configuration). + type: str backend_http_settings: description: - Backend http settings resource of the application gateway; used for the path's I(backend_address_pool). + type: str rewrite_rule_set: description: - Rewrite rule set for the path map. - Can be the name of the rewrite rule set or full resource ID. + type: str version_added: "1.11.0" redirect_configuration: description: - Name of redirect configuration resource of the application gateway which will be used if the path is matched. - Mutually exclusive with I(backend_address_pool). + type: str version_added: "1.10.0" paths: description: @@ -616,6 +708,7 @@ options: description: - Name of redirect configuration resource of the application gateway which will be used if no path matches occur. - Mutually exclusive with I(default_backend_address_pool). + type: str version_added: "1.10.0" request_routing_rules: description: @@ -626,31 +719,39 @@ options: rule_type: description: - Rule type. + type: str choices: - 'basic' - 'path_based_routing' backend_address_pool: description: - Backend address pool resource of the application gateway. Not used if I(rule_type) is C(path_based_routing). + type: raw backend_http_settings: description: - Backend C(http) settings resource of the application gateway. + type: raw http_listener: description: - Http listener resource of the application gateway. + type: raw name: description: - Name of the resource that is unique within a resource group. This name can be used to access the resource. + type: str redirect_configuration: description: - Redirect configuration resource of the application gateway. + type: raw url_path_map: description: - URL path map resource of the application gateway. Required if I(rule_type) is C(path_based_routing). + type: raw rewrite_rule_set: description: - Rewrite rule set for the path map. - Can be the name of the rewrite rule set or full resource ID. + type: raw version_added: "1.11.0" autoscale_configuration: version_added: "1.15.0" @@ -683,6 +784,7 @@ options: - The disabled rule groups. type: list elements: dict + default: [] suboptions: rule_group_name: description: @@ -693,6 +795,7 @@ options: - The list of rules that will be disabled. If null, all rules of the rule group will be disabled. type: list elements: int + default: [] enabled: description: - Whether the web application firewall is enabled or not. @@ -702,6 +805,7 @@ options: - The exclusion list. type: list elements: dict + default: [] suboptions: match_variable: description: @@ -761,6 +865,7 @@ options: description: - Assert the state of the application gateway. Use C(present) to create or update and C(absent) to delete. default: present + type: str choices: - absent - present @@ -803,15 +908,15 @@ EXAMPLES = ''' protocol: http cookie_based_affinity: enabled connection_draining: - drain_timeout_in_sec: 60 - enabled: true + drain_timeout_in_sec: 60 + enabled: true name: sample_appgateway_http_settings http_listeners: - frontend_ip_configuration: sample_gateway_frontend_ip_config frontend_port: ag_frontend_port name: sample_http_listener request_routing_rules: - - rule_type: Basic + - rule_type: basic backend_address_pool: test_backend_address_pool backend_http_settings: sample_appgateway_http_settings http_listener: sample_http_listener @@ -848,8 +953,8 @@ EXAMPLES = ''' protocol: http cookie_based_affinity: enabled connection_draining: - drain_timeout_in_sec: 60 - enabled: true + drain_timeout_in_sec: 60 + enabled: true name: sample_appgateway_http_settings trusted_root_certificates: - "root_cert" @@ -858,7 +963,7 @@ EXAMPLES = ''' frontend_port: ag_frontend_port name: sample_http_listener request_routing_rules: - - rule_type: Basic + - rule_type: basic backend_address_pool: test_backend_address_pool backend_http_settings: sample_appgateway_http_settings http_listener: sample_http_listener @@ -899,7 +1004,7 @@ EXAMPLES = ''' frontend_port: ag_frontend_port name: sample_http_listener request_routing_rules: - - rule_type: Basic + - rule_type: basic backend_address_pool: test_backend_address_pool backend_http_settings: sample_appgateway_http_settings http_listener: sample_http_listener @@ -1196,20 +1301,20 @@ EXAMPLES = ''' - header_name: "Foo" header_value: "Bar" probes: - - name: "http-probe1" - interval: 30 - path: "/abc" - protocol: "https" - pick_host_name_from_backend_http_settings: true - timeout: 30 - unhealthy_threshold: 2 - - name: "http-probe2" - interval: 30 - path: "/xyz" - protocol: "http" - pick_host_name_from_backend_http_settings: true - timeout: 30 - unhealthy_threshold: 2 + - name: "http-probe1" + interval: 30 + path: "/abc" + protocol: "https" + pick_host_name_from_backend_http_settings: true + timeout: 30 + unhealthy_threshold: 2 + - name: "http-probe2" + interval: 30 + path: "/xyz" + protocol: "http" + pick_host_name_from_backend_http_settings: true + timeout: 30 + unhealthy_threshold: 2 redirect_configurations: - name: "redirect-http" redirect_type: "permanent" @@ -1261,7 +1366,7 @@ EXAMPLES = ''' frontend_port: ag_frontend_port name: sample_http_listener request_routing_rules: - - rule_type: Basic + - rule_type: basic backend_address_pool: test_backend_address_pool backend_http_settings: sample_appgateway_http_settings http_listener: sample_http_listener @@ -1300,7 +1405,7 @@ EXAMPLES = ''' frontend_port: ag_frontend_port name: sample_http_listener request_routing_rules: - - rule_type: Basic + - rule_type: basic backend_address_pool: test_backend_address_pool backend_http_settings: sample_appgateway_http_settings http_listener: sample_http_listener @@ -1376,7 +1481,7 @@ from ansible.module_utils.common.dict_transformations import ( try: from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from msrestazure.tools import parse_resource_id, is_valid_resource_id + from azure.mgmt.core.tools import parse_resource_id, is_valid_resource_id except ImportError: # This is handled in azure_rm_common pass @@ -1394,11 +1499,21 @@ sku_spec = dict( ssl_policy_spec = dict( - disabled_ssl_protocols=dict(type='list'), + disabled_ssl_protocols=dict(type='list', elements='str', choices=['tls_v1_0', 'tls_v1_1', 'tls_v1_2']), policy_type=dict(type='str', choices=['predefined', 'custom']), policy_name=dict(type='str', choices=['ssl_policy20150501', 'ssl_policy20170401', 'ssl_policy20170401_s']), - cipher_suites=dict(type='list'), - min_protocol_version=dict(type='str', choices=['tls_v1_0', 'tls_v1_1', 'tls_v1_2']) + min_protocol_version=dict(type='str', choices=['tls_v1_0', 'tls_v1_1', 'tls_v1_2']), + cipher_suites=dict(type='list', elements='str', + choices=['tls_ecdhe_rsa_with_aes_256_gcm_sha384', 'tls_ecdhe_rsa_with_aes_128_gcm_sha256', 'tls_ecdhe_rsa_with_aes_256_cbc_sha384', + 'tls_ecdhe_rsa_with_aes_128_cbc_sha256', 'tls_ecdhe_rsa_with_aes_256_cbc_sha', 'tls_ecdhe_rsa_with_aes_128_cbc_sha', + 'tls_dhe_rsa_with_aes_256_gcm_sha384', 'tls_dhe_rsa_with_aes_128_gcm_sha256', 'tls_dhe_rsa_with_aes_256_cbc_sha', + 'tls_dhe_rsa_with_aes_128_cbc_sha', 'tls_rsa_with_aes_256_gcm_sha384', 'tls_rsa_with_aes_128_gcm_sha256', + 'tls_rsa_with_aes_256_cbc_sha256', 'tls_rsa_with_aes_128_cbc_sha256', 'tls_rsa_with_aes_256_cbc_sha', + 'tls_rsa_with_aes_128_cbc_sha', 'tls_ecdhe_ecdsa_with_aes_256_gcm_sha384', 'tls_ecdhe_ecdsa_with_aes_128_gcm_sha256', + 'tls_ecdhe_ecdsa_with_aes_256_cbc_sha384', 'tls_ecdhe_ecdsa_with_aes_128_cbc_sha256', + 'tls_ecdhe_ecdsa_with_aes_256_cbc_sha', 'tls_ecdhe_ecdsa_with_aes_128_cbc_sha', 'tls_dhe_dss_with_aes_256_cbc_sha256', + 'tls_dhe_dss_with_aes_128_cbc_sha256', 'tls_dhe_dss_with_aes_256_cbc_sha', 'tls_dhe_dss_with_aes_128_cbc_sha', + 'tls_rsa_with_3des_ede_cbc_sha', 'tls_dhe_dss_with_3des_ede_cbc_sha']), ) @@ -1561,13 +1676,36 @@ class AzureRMApplicationGateways(AzureRMModuleBase): options=ssl_policy_spec ), gateway_ip_configurations=dict( - type='list' + type='list', + elements='dict', + options=dict( + name=dict(type='str'), + subnet=dict( + type='dict', + options=dict( + id=dict(type='str'), + name=dict(type='str'), + virtual_network_name=dict(type='str') + ) + ) + ) ), authentication_certificates=dict( - type='list' + type='list', + elements='dict', + options=dict( + name=dict(type='str'), + data=dict(type='str') + ), ), ssl_certificates=dict( - type='list' + type='list', + elements='dict', + options=dict( + data=dict(type='str'), + password=dict(type='str', no_log=True), + name=dict(type='str') + ) ), trusted_root_certificates=dict( type='list', @@ -1585,16 +1723,76 @@ class AzureRMApplicationGateways(AzureRMModuleBase): options=rewrite_rule_set_spec ), frontend_ip_configurations=dict( - type='list' + type='list', + elements='dict', + options=dict( + private_ip_address=dict(type='str'), + private_ip_allocation_method=dict(type='str', choices=['static', 'dynamic']), + public_ip_address=dict(type='raw'), + name=dict(type='str'), + subnet=dict( + type='dict', + options=dict( + id=dict(type='str'), + name=dict(type='str'), + virtual_network_name=dict(type='str') + ) + ) + ) ), frontend_ports=dict( - type='list' + type='list', + elements='dict', + options=dict( + port=dict(type='str'), + name=dict(type='str') + ) ), backend_address_pools=dict( - type='list' + type='list', + elements='dict', + options=dict( + name=dict(type='str'), + backend_addresses=dict( + type='list', + elements='dict', + options=dict( + fqdn=dict(type='str'), + ip_address=dict(type='str') + ) + ) + ) ), backend_http_settings_collection=dict( - type='list' + type='list', + elements='dict', + options=dict( + probe=dict(type='raw'), + port=dict(type='int'), + protocol=dict(type='str', choices=['http', 'https']), + cookie_based_affinity=dict(type='str', choices=['enabled', 'disabled']), + connection_draining=dict( + type='dict', + options=dict( + drain_timeout_in_sec=dict(type='int'), + enabled=dict(type='bool') + ) + ), + request_timeout=dict(type='int'), + authentication_certificates=dict( + type='list', + elements='dict', + options=dict( + id=dict(type='str') + ) + ), + trusted_root_certificates=dict(type='list', elements='raw'), + host_name=dict(type='str'), + pick_host_name_from_backend_address=dict(type='bool'), + affinity_cookie_name=dict(type='str'), + path=dict(type='str'), + name=dict(type='str') + ) ), probes=dict( type='list', @@ -1602,7 +1800,17 @@ class AzureRMApplicationGateways(AzureRMModuleBase): options=probe_spec ), http_listeners=dict( - type='list' + type='list', + elements='dict', + options=dict( + frontend_ip_configuration=dict(type='raw'), + frontend_port=dict(type='raw'), + protocol=dict(type='str', choices=['http', 'https']), + host_name=dict(type='str'), + ssl_certificate=dict(type='raw'), + require_server_name_indication=dict(type='bool'), + name=dict(type='str'), + ) ), url_path_maps=dict( type='list', @@ -1613,7 +1821,18 @@ class AzureRMApplicationGateways(AzureRMModuleBase): required_together=[('default_backend_address_pool', 'default_backend_http_settings')], ), request_routing_rules=dict( - type='list' + type='list', + elements='dict', + options=dict( + rule_type=dict(type='str', choices=['basic', 'path_based_routing']), + backend_address_pool=dict(type='raw'), + backend_http_settings=dict(type='raw'), + http_listener=dict(type='raw'), + name=dict(type='str'), + redirect_configuration=dict(type='raw'), + rewrite_rule_set=dict(type='raw'), + url_path_map=dict(type='raw'), + ) ), autoscale_configuration=dict( type='dict', @@ -1730,7 +1949,8 @@ class AzureRMApplicationGateways(AzureRMModuleBase): ev = kwargs[key] for i in range(len(ev)): item = ev[i] - if 'subnet' in item and 'name' in item['subnet'] and 'virtual_network_name' in item['subnet']: + if 'subnet' in item and item['subnet'] is not None and 'name' in item['subnet'] and item['subnet']['name'] is not None and \ + 'virtual_network_name' in item['subnet'] and item['subnet']['virtual_network_name'] is not None: id = subnet_id(self.subscription_id, kwargs['resource_group'], item['subnet']['virtual_network_name'], @@ -1806,14 +2026,15 @@ class AzureRMApplicationGateways(AzureRMModuleBase): ev = kwargs[key] for i in range(len(ev)): item = ev[i] - if 'private_ip_allocation_method' in item: + if 'private_ip_allocation_method' in item and item['private_ip_allocation_method'] is not None: item['private_ip_allocation_method'] = _snake_to_camel(item['private_ip_allocation_method'], True) - if 'public_ip_address' in item: + if 'public_ip_address' in item and item['public_ip_address'] is not None: id = public_ip_id(self.subscription_id, kwargs['resource_group'], item['public_ip_address']) item['public_ip_address'] = {'id': id} - if 'subnet' in item and 'name' in item['subnet'] and 'virtual_network_name' in item['subnet']: + if 'subnet' in item and item['subnet'] is not None and 'name' in item['subnet'] and item['subnet']['name'] is not None and \ + 'virtual_network_name' in item['subnet'] and item['subnet']['virtual_network_name'] is not None: id = subnet_id(self.subscription_id, kwargs['resource_group'], item['subnet']['virtual_network_name'], @@ -1828,7 +2049,7 @@ class AzureRMApplicationGateways(AzureRMModuleBase): ev = kwargs[key] for i in range(len(ev)): item = ev[i] - if 'protocol' in item: + if 'protocol' in item and item['protocol'] is not None: item['protocol'] = _snake_to_camel(item['protocol'], True) if 'pick_host_name_from_backend_http_settings' in item and item['pick_host_name_from_backend_http_settings'] and 'host' in item: del item['host'] @@ -1837,17 +2058,17 @@ class AzureRMApplicationGateways(AzureRMModuleBase): ev = kwargs[key] for i in range(len(ev)): item = ev[i] - if 'protocol' in item: + if 'protocol' in item and item['protocol'] is not None: item['protocol'] = _snake_to_camel(item['protocol'], True) - if 'cookie_based_affinity' in item: + if 'cookie_based_affinity' in item and item['cookie_based_affinity'] is not None: item['cookie_based_affinity'] = _snake_to_camel(item['cookie_based_affinity'], True) - if 'probe' in item: + if 'probe' in item and item['probe'] is not None: id = probe_id(self.subscription_id, kwargs['resource_group'], kwargs['name'], item['probe']) item['probe'] = {'id': id} - if 'trusted_root_certificates' in item: + if 'trusted_root_certificates' in item and item['trusted_root_certificates'] is not None: for j in range(len(item['trusted_root_certificates'])): id = item['trusted_root_certificates'][j] id = id if is_valid_resource_id(id) else trusted_root_certificate_id(self.subscription_id, @@ -1860,26 +2081,26 @@ class AzureRMApplicationGateways(AzureRMModuleBase): ev = kwargs[key] for i in range(len(ev)): item = ev[i] - if 'frontend_ip_configuration' in item: + if 'frontend_ip_configuration' in item and item['frontend_ip_configuration'] is not None: id = frontend_ip_configuration_id(self.subscription_id, kwargs['resource_group'], kwargs['name'], item['frontend_ip_configuration']) item['frontend_ip_configuration'] = {'id': id} - if 'frontend_port' in item: + if 'frontend_port' in item and item['frontend_port'] is not None: id = frontend_port_id(self.subscription_id, kwargs['resource_group'], kwargs['name'], item['frontend_port']) item['frontend_port'] = {'id': id} - if 'ssl_certificate' in item: + if 'ssl_certificate' in item and item['ssl_certificate'] is not None: id = ssl_certificate_id(self.subscription_id, kwargs['resource_group'], kwargs['name'], item['ssl_certificate']) item['ssl_certificate'] = {'id': id} - if 'protocol' in item: + if 'protocol' in item and item['protocol'] is not None: item['protocol'] = _snake_to_camel(item['protocol'], True) ev[i] = item self.parameters["http_listeners"] = ev @@ -1887,7 +2108,7 @@ class AzureRMApplicationGateways(AzureRMModuleBase): ev = kwargs[key] for i in range(len(ev)): item = ev[i] - if item['default_backend_address_pool']: + if item['default_backend_address_pool'] and item['default_backend_address_pool'] is not None: id = backend_address_pool_id(self.subscription_id, kwargs['resource_group'], kwargs['name'], @@ -1895,7 +2116,7 @@ class AzureRMApplicationGateways(AzureRMModuleBase): item['default_backend_address_pool'] = {'id': id} else: del item['default_backend_address_pool'] - if item['default_backend_http_settings']: + if item['default_backend_http_settings'] and item['default_backend_http_settings'] is not None: id = backend_http_settings_id(self.subscription_id, kwargs['resource_group'], kwargs['name'], @@ -1907,7 +2128,7 @@ class AzureRMApplicationGateways(AzureRMModuleBase): ev2 = item['path_rules'] for j in range(len(ev2)): item2 = ev2[j] - if item2['backend_address_pool']: + if item2['backend_address_pool'] and item2['backend_address_pool'] is not None: id = backend_address_pool_id(self.subscription_id, kwargs['resource_group'], kwargs['name'], @@ -1915,7 +2136,7 @@ class AzureRMApplicationGateways(AzureRMModuleBase): item2['backend_address_pool'] = {'id': id} else: del item2['backend_address_pool'] - if item2['backend_http_settings']: + if item2['backend_http_settings'] and item2['backend_http_settings'] is not None: id = backend_http_settings_id(self.subscription_id, kwargs['resource_group'], kwargs['name'], @@ -1923,7 +2144,7 @@ class AzureRMApplicationGateways(AzureRMModuleBase): item2['backend_http_settings'] = {'id': id} else: del item2['backend_http_settings'] - if item2['redirect_configuration']: + if item2['redirect_configuration'] and item2['redirect_configuration'] is not None: id = redirect_configuration_id(self.subscription_id, kwargs['resource_group'], kwargs['name'], @@ -1964,37 +2185,38 @@ class AzureRMApplicationGateways(AzureRMModuleBase): ev = kwargs[key] for i in range(len(ev)): item = ev[i] - if 'rule_type' in item and item['rule_type'] == 'path_based_routing' and 'backend_address_pool' in item: + if 'rule_type' in item and item['rule_type'] is not None and item['rule_type'] == 'path_based_routing' and \ + 'backend_address_pool' in item and item['backend_address_pool'] is not None: del item['backend_address_pool'] - if 'backend_address_pool' in item: + if 'backend_address_pool' in item and item['backend_address_pool'] is not None: id = backend_address_pool_id(self.subscription_id, kwargs['resource_group'], kwargs['name'], item['backend_address_pool']) item['backend_address_pool'] = {'id': id} - if 'backend_http_settings' in item: + if 'backend_http_settings' in item and item['backend_http_settings'] is not None: id = backend_http_settings_id(self.subscription_id, kwargs['resource_group'], kwargs['name'], item['backend_http_settings']) item['backend_http_settings'] = {'id': id} - if 'http_listener' in item: + if 'http_listener' in item and item['http_listener'] is not None: id = http_listener_id(self.subscription_id, kwargs['resource_group'], kwargs['name'], item['http_listener']) item['http_listener'] = {'id': id} - if 'protocol' in item: + if 'protocol' in item and item['protocol'] is not None: item['protocol'] = _snake_to_camel(item['protocol'], True) - if 'rule_type' in item: + if 'rule_type' in item and item['rule_type'] is not None: item['rule_type'] = _snake_to_camel(item['rule_type'], True) - if 'redirect_configuration' in item: + if 'redirect_configuration' in item and item['redirect_configuration'] is not None: id = redirect_configuration_id(self.subscription_id, kwargs['resource_group'], kwargs['name'], item['redirect_configuration']) item['redirect_configuration'] = {'id': id} - if 'url_path_map' in item: + if 'url_path_map' in item and item['url_path_map'] is not None: id = url_path_map_id(self.subscription_id, kwargs['resource_group'], kwargs['name'], diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appgateway_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appgateway_info.py index da5c5ecd2..f6ede2a71 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appgateway_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appgateway_info.py @@ -33,17 +33,17 @@ author: ''' EXAMPLES = ''' - - name: Get facts for application gateway by name. - azure_rm_appgateway_info: - name: MyAppgw - resource_group: MyResourceGroup +- name: Get facts for application gateway by name. + azure_rm_appgateway_info: + name: MyAppgw + resource_group: MyResourceGroup - - name: Get facts for application gateways in resource group. - azure_rm_appgateway_info: - resource_group: MyResourceGroup +- name: Get facts for application gateways in resource group. + azure_rm_appgateway_info: + resource_group: MyResourceGroup - - name: Get facts for all application gateways. - azure_rm_appgateway_info: +- name: Get facts for all application gateways. + azure_rm_appgateway_info: ''' RETURN = ''' @@ -116,7 +116,7 @@ from ansible.module_utils.common.dict_transformations import _camel_to_snake try: from azure.core.exceptions import ResourceNotFoundError - from msrestazure.tools import parse_resource_id + from azure.mgmt.core.tools import parse_resource_id except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_applicationsecuritygroup.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_applicationsecuritygroup.py index d135ca193..630142785 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_applicationsecuritygroup.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_applicationsecuritygroup.py @@ -21,21 +21,25 @@ options: description: - The name of the resource group. required: True + type: str name: description: - The name of the application security group. required: True + type: str location: description: - Resource location. If not set, location from the resource group will be used as default. + type: str state: - description: - - Assert the state of the Application Security Group. - - Use C(present) to create or update an Application Security Group and C(absent) to delete it. - default: present - choices: - - absent - - present + description: + - Assert the state of the Application Security Group. + - Use C(present) to create or update an Application Security Group and C(absent) to delete it. + type: str + default: present + choices: + - absent + - present extends_documentation_fragment: - azure.azcollection.azure @@ -47,13 +51,13 @@ author: ''' EXAMPLES = ''' - - name: Create application security group - azure_rm_applicationsecuritygroup: - resource_group: myResourceGroup - name: mySecurityGroup - location: eastus - tags: - foo: bar +- name: Create application security group + azure_rm_applicationsecuritygroup: + resource_group: myResourceGroup + name: mySecurityGroup + location: eastus + tags: + foo: bar ''' RETURN = ''' @@ -71,7 +75,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from msrestazure.azure_operation import AzureOperationPoller except ImportError: # This is handled in azure_rm_common pass @@ -193,7 +196,7 @@ class AzureRMApplicationSecurityGroup(AzureRMModuleBase): response = self.network_client.application_security_groups.begin_create_or_update(resource_group_name=self.resource_group, application_security_group_name=self.name, parameters=param) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_applicationsecuritygroup_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_applicationsecuritygroup_info.py index 738404b4e..9e758c6ed 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_applicationsecuritygroup_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_applicationsecuritygroup_info.py @@ -20,9 +20,11 @@ options: resource_group: description: - The name of the resource group. + type: str name: description: - The name of the application security group. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -38,19 +40,19 @@ author: ''' EXAMPLES = ''' - - name: List application security groups in specific resource group - azure_rm_applicationsecuritygroup_info: - resource_group: myResourceGroup - - - name: List application security groups in specific subscription - azure_rm_applicationsecuritygroup_info: - - - name: Get application security group by name - azure_rm_applicationsecuritygroup_info: - resource_group: myResourceGroup - name: myApplicationSecurityGroup - tags: - - foo +- name: List application security groups in specific resource group + azure_rm_applicationsecuritygroup_info: + resource_group: myResourceGroup + +- name: List application security groups in specific subscription + azure_rm_applicationsecuritygroup_info: + +- name: Get application security group by name + azure_rm_applicationsecuritygroup_info: + resource_group: myResourceGroup + name: myApplicationSecurityGroup + tags: + - foo ''' RETURN = ''' @@ -90,7 +92,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError - from msrestazure.azure_operation import AzureOperationPoller except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appserviceplan.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appserviceplan.py index 2c0e883bf..1ca293f8a 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appserviceplan.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appserviceplan.py @@ -21,21 +21,24 @@ options: description: - Name of the resource group to which the resource belongs. required: True + type: str name: description: - Unique name of the app service plan to create or update. required: True + type: str location: description: - Resource location. If not set, location from the resource group will be used as default. - + type: str sku: description: - The pricing tiers, e.g., C(F1), C(D1), C(B1), C(B2), C(B3), C(S1), C(P1), C(P1V2) etc. - Please see U(https://azure.microsoft.com/en-us/pricing/details/app-service/plans/) for more detail. - For Linux app service plan, please see U(https://azure.microsoft.com/en-us/pricing/details/app-service/linux/) for more detail. + type: str is_linux: description: - Describe whether to host webapp on Linux worker. @@ -45,15 +48,17 @@ options: number_of_workers: description: - Describe number of workers to be allocated. + type: str state: - description: - - Assert the state of the app service plan. - - Use C(present) to create or update an app service plan and C(absent) to delete it. - default: present - choices: - - absent - - present + description: + - Assert the state of the app service plan. + - Use C(present) to create or update an app service plan and C(absent) to delete it. + default: present + type: str + choices: + - absent + - present extends_documentation_fragment: - azure.azcollection.azure @@ -65,28 +70,28 @@ author: ''' EXAMPLES = ''' - - name: Create a windows app service plan - azure_rm_appserviceplan: - resource_group: myResourceGroup - name: myAppPlan - location: eastus - sku: S1 - - - name: Create a linux app service plan - azure_rm_appserviceplan: - resource_group: myResourceGroup - name: myAppPlan - location: eastus - sku: S1 - is_linux: true - number_of_workers: 1 - - - name: update sku of existing windows app service plan - azure_rm_appserviceplan: - resource_group: myResourceGroup - name: myAppPlan - location: eastus - sku: S2 +- name: Create a windows app service plan + azure_rm_appserviceplan: + resource_group: myResourceGroup + name: myAppPlan + location: eastus + sku: S1 + +- name: Create a linux app service plan + azure_rm_appserviceplan: + resource_group: myResourceGroup + name: myAppPlan + location: eastus + sku: S1 + is_linux: true + number_of_workers: 1 + +- name: update sku of existing windows app service plan + azure_rm_appserviceplan: + resource_group: myResourceGroup + name: myAppPlan + location: eastus + sku: S2 ''' RETURN = ''' @@ -99,13 +104,11 @@ azure_appserviceplan: } ''' -import time from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from msrestazure.azure_operation import AzureOperationPoller from azure.mgmt.web.models import AppServicePlan, SkuDescription except ImportError: # This is handled in azure_rm_common @@ -337,7 +340,7 @@ class AzureRMAppServicePlans(AzureRMModuleBase): name=self.name, app_service_plan=plan_def) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) self.log("Response : {0}".format(response)) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appserviceplan_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appserviceplan_info.py index 826ecc175..c57570976 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appserviceplan_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appserviceplan_info.py @@ -23,9 +23,11 @@ options: name: description: - Only show results for a specific app service plan. + type: str resource_group: description: - Limit results by resource group. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -40,20 +42,20 @@ author: ''' EXAMPLES = ''' - - name: Get facts for app service plan by name - azure_rm_appserviceplan_info: - resource_group: myResourceGroup - name: myAppServicePlan - - - name: Get azure_rm_appserviceplan_facts for app service plan in resource group - azure_rm_appserviceplan_info: - resource_group: myResourceGroup - - - name: Get facts for app service plan with tags - azure_rm_appserviceplan_info: - tags: - - testtag - - foo:bar +- name: Get facts for app service plan by name + azure_rm_appserviceplan_info: + resource_group: myResourceGroup + name: myAppServicePlan + +- name: Get azure_rm_appserviceplan_facts for app service plan in resource group + azure_rm_appserviceplan_info: + resource_group: myResourceGroup + +- name: Get facts for app service plan with tags + azure_rm_appserviceplan_info: + tags: + - testtag + - foo:bar ''' RETURN = ''' @@ -217,14 +219,14 @@ class AzureRMAppServicePlanInfo(AzureRMModuleBase): curated_output = dict() curated_output['id'] = plan_facts['id'] curated_output['name'] = plan_facts['name'] - curated_output['resource_group'] = plan_facts['properties']['resourceGroup'] + curated_output['resource_group'] = plan_facts['resource_group'] curated_output['location'] = plan_facts['location'] curated_output['tags'] = plan_facts.get('tags', None) curated_output['is_linux'] = False curated_output['kind'] = plan_facts['kind'] curated_output['sku'] = plan_facts['sku'] - if plan_facts['properties'].get('reserved', None): + if plan_facts.get('reserved', None): curated_output['is_linux'] = True return curated_output diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_automationaccount_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_automationaccount_info.py index defbb7f2a..dd02169d9 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_automationaccount_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_automationaccount_info.py @@ -58,18 +58,18 @@ author: EXAMPLES = ''' - name: Get details of an automation account azure_rm_automationaccount_info: - name: Testing - resource_group: myResourceGroup - list_statistics: yes - list_usages: yes - list_keys: yes - tags: - - key - - key:value + name: Testing + resource_group: myResourceGroup + list_statistics: true + list_usages: true + list_keys: true + tags: + - key + - key:value - name: List automation account in a resource group azure_rm_automationaccount_info: - resource_group: myResourceGroup + resource_group: myResourceGroup - name: List automation account in a resource group azure_rm_automationaccount_info: @@ -240,7 +240,7 @@ automation_accounts: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: - from msrestazure.tools import parse_resource_id + from azure.mgmt.core.tools import parse_resource_id from azure.core.exceptions import ResourceNotFoundError except ImportError: pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_automationrunbook.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_automationrunbook.py index 5f4cc10b1..e983db439 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_automationrunbook.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_automationrunbook.py @@ -102,8 +102,8 @@ EXAMPLES = ''' runbook_type: "Script" description: "Fred test" log_activity_trace: 3 - log_progress: True - log_verbose: False + log_progress: true + log_verbose: false tags: key1: value1 @@ -112,7 +112,7 @@ EXAMPLES = ''' resource_group: "{{ resource_group }}" automation_account_name: "{{ account-name }}" name: "{{ runbook-name }}" - publish: True + publish: true - name: Delete automation runbook azure_rm_automationrunbook: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_automationrunbook_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_automationrunbook_info.py index 7f3385362..341edc3d9 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_automationrunbook_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_automationrunbook_info.py @@ -66,8 +66,7 @@ EXAMPLES = ''' resource_group: "{{ resource_group }}" automation_account_name: "{{ account-name }}" name: "{{ runbook-name }}" - show_content: True - + show_content: true ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_autoscale.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_autoscale.py index adcb6dfb9..f21505f81 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_autoscale.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_autoscale.py @@ -21,10 +21,12 @@ options: - The identifier of the resource to apply autoscale setting. - It could be the resource id string. - It also could be a dict contains the C(name), C(subscription_id), C(namespace), C(types), C(resource_group) of the resource. + type: raw resource_group: required: true description: - Resource group of the resource. + type: str enabled: type: bool description: @@ -34,29 +36,36 @@ options: description: - The collection of automatic scaling profiles that specify different scaling parameters for different time periods. - A maximum of 20 profiles can be specified. + type: list + elements: dict suboptions: name: required: true description: - The name of the profile. + type: str count: required: true description: - The number of instances that will be set if metrics are not available for evaluation. - The default is only used if the current instance count is lower than the default. + type: str min_count: description: - The minimum number of instances for the resource. + type: str max_count: description: - The maximum number of instances for the resource. - The actual maximum number of instances is limited by the cores that are available in the subscription. + type: str recurrence_frequency: default: None description: - How often the schedule profile should take effect. - If this value is C(Week), meaning each week will have the same set of profiles. - This element is not used if the FixedDate element is used. + type: str choices: - None - Second @@ -70,39 +79,52 @@ options: description: - The timezone of repeating times at which this profile begins. - This element is not used if the FixedDate element is used. + type: str recurrence_days: description: - The days of repeating times at which this profile begins. - This element is not used if the FixedDate element is used. + type: list + elements: str recurrence_hours: description: - The hours of repeating times at which this profile begins. - This element is not used if the FixedDate element is used. + type: list + elements: str recurrence_mins: description: - The mins of repeating times at which this profile begins. - This element is not used if the FixedDate element is used. + type: list + elements: str fixed_date_timezone: description: - The specific date-time timezone for the profile. - This element is not used if the Recurrence element is used. + type: str fixed_date_start: description: - The specific date-time start for the profile. - This element is not used if the Recurrence element is used. + type: str fixed_date_end: description: - The specific date-time end for the profile. - This element is not used if the Recurrence element is used. + type: str rules: description: - The collection of rules that provide the triggers and parameters for the scaling action. - A maximum of 10 rules can be specified. + type: list + elements: dict suboptions: time_aggregation: default: Average description: - How the data that is collected should be combined over time. + type: str choices: - Average - Minimum @@ -115,9 +137,11 @@ options: - The range of time(minutes) in which instance data is collected. - This value must be greater than the delay in metric collection, which can vary from resource-to-resource. - Must be between 5 ~ 720. + type: float direction: description: - Whether the scaling action increases or decreases the number of instances. + type: str choices: - Increase - Decrease @@ -125,17 +149,21 @@ options: required: true description: - The name of the metric that defines what the rule monitors. + type: str metric_resource_uri: description: - The resource identifier of the resource the rule monitors. + type: str value: description: - The number of instances that are involved in the scaling action. - This value must be 1 or greater. + type: str operator: default: GreaterThan description: - The operator that is used to compare the metric data and the threshold. + type: str choices: - Equals - NotEquals @@ -147,16 +175,19 @@ options: description: - The amount of time (minutes) to wait since the last scaling action before this action occurs. - It must be between 1 ~ 10080. + type: float time_grain: required: true description: - The granularity(minutes) of metrics the rule monitors. - Must be one of the predefined values returned from metric definitions for the metric. - Must be between 1 ~ 720. + type: float statistic: default: Average description: - How the metrics from multiple instances are combined. + type: str choices: - Average - Min @@ -166,9 +197,11 @@ options: default: 70 description: - The threshold of the metric that triggers the scale action. + type: float type: description: - The type of action that should occur when the scale rule fires. + type: str choices: - PercentChangeCount - ExactCount @@ -176,37 +209,50 @@ options: notifications: description: - The collection of notifications. + type: list + elements: dict suboptions: custom_emails: description: - The custom e-mails list. This value can be null or empty, in which case this attribute will be ignored. + type: list + elements: str send_to_subscription_administrator: type: bool default: False description: - A value indicating whether to send email to subscription administrator. + aliases: + - email_admin webhooks: description: - The list of webhook notifications service uri. + type: list + elements: str send_to_subscription_co_administrators: type: bool default: False description: - A value indicating whether to send email to subscription co-administrators. + aliases: + - email_co_admin state: default: present description: - Assert the state of the virtual network. Use C(present) to create or update and C(absent) to delete. + type: str choices: - present - absent location: description: - location of the resource. + type: str name: required: true description: - name of the resource. + type: str extends_documentation_fragment: @@ -221,63 +267,63 @@ author: EXAMPLES = ''' - name: Create an auto scale azure_rm_autoscale: - target: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachineScaleSets/myVmss" - enabled: true - profiles: + target: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachineScaleSets/myVmss" + enabled: true + profiles: - count: '1' recurrence_days: - - Monday + - Monday name: Auto created scale condition recurrence_timezone: China Standard Time recurrence_mins: - - '0' + - '0' min_count: '1' max_count: '1' recurrence_frequency: Week recurrence_hours: - - '18' - name: scale - resource_group: myResourceGroup + - '18' + name: scale + resource_group: myResourceGroup - name: Create an auto scale with complicated profile azure_rm_autoscale: - target: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachineScaleSets + target: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachineScaleSets /myVmss" - enabled: true - profiles: + enabled: true + profiles: - count: '1' recurrence_days: - - Monday + - Monday name: Auto created scale condition 0 rules: - - time_aggregation: Average - time_window: 10 - direction: Increase - metric_name: Percentage CPU - metric_resource_uri: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtua + - time_aggregation: Average + time_window: 10 + direction: Increase + metric_name: Percentage CPU + metric_resource_uri: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtua lMachineScaleSets/vmss" - value: '1' - threshold: 70 - cooldown: 5 - time_grain: 1 - statistic: Average - operator: GreaterThan - type: ChangeCount + value: '1' + threshold: 70 + cooldown: 5 + time_grain: 1 + statistic: Average + operator: GreaterThan + type: ChangeCount max_count: '1' recurrence_mins: - - '0' + - '0' min_count: '1' recurrence_timezone: China Standard Time recurrence_frequency: Week recurrence_hours: - - '6' - notifications: - - email_admin: True - email_co_admin: False + - '6' + notifications: + - email_admin: true + email_co_admin: false custom_emails: - - yuwzho@microsoft.com - name: scale - resource_group: myResourceGroup + - yuwzho@microsoft.com + name: scale + resource_group: myResourceGroup - name: Delete an Azure Auto Scale Setting azure_rm_autoscale: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_autoscale_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_autoscale_info.py index 49411ad48..db5ebfea3 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_autoscale_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_autoscale_info.py @@ -21,9 +21,11 @@ options: description: - The name of the resource group. required: True + type: str name: description: - The name of the Auto Scale Setting. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -39,17 +41,17 @@ author: ''' EXAMPLES = ''' - - name: Get instance of Auto Scale Setting - azure_rm_autoscale_info: - resource_group: myResourceGroup - name: auto_scale_name - - - name: List instances of Auto Scale Setting - azure_rm_autoscale_info: - resource_group: myResourceGroup - tags: - - key - - key:value +- name: Get instance of Auto Scale Setting + azure_rm_autoscale_info: + resource_group: myResourceGroup + name: auto_scale_name + +- name: List instances of Auto Scale Setting + azure_rm_autoscale_info: + resource_group: myResourceGroup + tags: + - key + - key:value ''' RETURN = ''' @@ -117,12 +119,6 @@ autoscales: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from ansible.module_utils._text import to_native -try: - from msrest.serialization import Model -except ImportError: - # This is handled in azure_rm_common - pass - # duplicated in azure_rm_autoscale def timedelta_to_minutes(time): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_availabilityset.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_availabilityset.py index 1188a07c5..1ba334eba 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_availabilityset.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_availabilityset.py @@ -25,21 +25,25 @@ options: description: - Name of a resource group where the availability set exists or will be created. required: true + type: str name: description: - Name of the availability set. + type: str required: true state: description: - Assert the state of the availability set. - Use C(present) to create or update a availability set and C(absent) to delete a availability set. default: present + type: str choices: - absent - present location: description: - Valid Azure location. Defaults to location of the resource group. + type: str platform_update_domain_count: description: - Update domains indicate groups of virtual machines and underlying physical hardware that can be rebooted at the same time. @@ -59,6 +63,7 @@ options: description: - Define if the availability set supports managed disks. default: Classic + type: str choices: - Classic - Aligned @@ -71,28 +76,28 @@ author: ''' EXAMPLES = ''' - - name: Create an availability set with default options - azure_rm_availabilityset: - name: myAvailabilitySet - location: eastus - resource_group: myResourceGroup - - - name: Create an availability set with advanced options - azure_rm_availabilityset: - name: myAvailabilitySet - location: eastus - resource_group: myResourceGroup - platform_update_domain_count: 5 - platform_fault_domain_count: 3 - proximity_placement_group: myProximityPlacementGroup - sku: Aligned - - - name: Delete an availability set - azure_rm_availabilityset: - name: myAvailabilitySet - location: eastus - resource_group: myResourceGroup - state: absent +- name: Create an availability set with default options + azure_rm_availabilityset: + name: myAvailabilitySet + location: eastus + resource_group: myResourceGroup + +- name: Create an availability set with advanced options + azure_rm_availabilityset: + name: myAvailabilitySet + location: eastus + resource_group: myResourceGroup + platform_update_domain_count: 5 + platform_fault_domain_count: 3 + proximity_placement_group: myProximityPlacementGroup + sku: Aligned + +- name: Delete an availability set + azure_rm_availabilityset: + name: myAvailabilitySet + location: eastus + resource_group: myResourceGroup + state: absent ''' RETURN = ''' @@ -152,7 +157,7 @@ changed: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: - from msrestazure.tools import parse_resource_id + from azure.mgmt.core.tools import parse_resource_id from azure.core.exceptions import ResourceNotFoundError except ImportError: # This is handled in azure_rm_common diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_availabilityset_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_availabilityset_info.py index 16122f67a..95050263b 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_availabilityset_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_availabilityset_info.py @@ -41,18 +41,17 @@ author: ''' EXAMPLES = ''' - - name: Get facts for one availability set - azure_rm_availabilityset_info: - name: Testing - resource_group: myResourceGroup - - - name: Get facts for all availability sets in a specific resource group - azure_rm_availabilityset_info: - resource_group: myResourceGroup - tags: - - key - - key:value - +- name: Get facts for one availability set + azure_rm_availabilityset_info: + name: Testing + resource_group: myResourceGroup + +- name: Get facts for all availability sets in a specific resource group + azure_rm_availabilityset_info: + resource_group: myResourceGroup + tags: + - key + - key:value ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_azurefirewall.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_azurefirewall.py index 099fb57fc..f960f024d 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_azurefirewall.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_azurefirewall.py @@ -34,6 +34,7 @@ options: description: - Collection of application rule collections used by Azure Firewall. type: list + elements: dict suboptions: priority: description: @@ -50,6 +51,7 @@ options: description: - Collection of rules used by a application rule collection. type: list + elements: raw suboptions: name: description: @@ -63,18 +65,31 @@ options: description: - List of source IP addresses for this rule. type: list + elements: str protocols: description: - Array of ApplicationRuleProtocols. + elements: dict type: list + suboptions: + type: + description: + - The type of the protocols. + type: str + port: + description: + - The ports of the protocols. + type: str target_fqdns: description: - List of FQDNs for this rule. type: list + elements: raw fqdn_tags: description: - List of FQDN Tags for this rule. type: list + elements: raw name: description: - Gets name of the resource that is unique within a resource group. @@ -84,6 +99,7 @@ options: description: - Collection of NAT rule collections used by Azure Firewall. type: list + elements: dict suboptions: priority: description: @@ -100,6 +116,7 @@ options: description: - Collection of rules used by a NAT rule collection. type: list + elements: dict suboptions: name: description: @@ -113,18 +130,22 @@ options: description: - List of source IP addresses for this rule. type: list + elements: str destination_addresses: description: - List of destination IP addresses for this rule. type: list + elements: str destination_ports: description: - List of destination ports. type: list + elements: str protocols: description: - Array of AzureFirewallNetworkRuleProtocols applicable to this NAT rule. type: list + elements: raw translated_address: description: - The translated address for this NAT rule. @@ -142,6 +163,7 @@ options: description: - Collection of network rule collections used by Azure Firewall. type: list + elements: dict suboptions: priority: description: @@ -158,6 +180,7 @@ options: description: - Collection of rules used by a network rule collection. type: list + elements: dict suboptions: name: description: @@ -171,18 +194,22 @@ options: description: - Array of AzureFirewallNetworkRuleProtocols. type: list + elements: raw source_addresses: description: - List of source IP addresses for this rule. type: list + elements: str destination_addresses: description: - List of destination IP addresses. type: list + elements: str destination_ports: description: - List of destination ports. type: list + elements: str name: description: - Gets name of the resource that is unique within a resource group. @@ -192,6 +219,7 @@ options: description: - IP configuration of the Azure Firewall resource. type: list + elements: dict suboptions: subnet: description: @@ -300,7 +328,6 @@ EXAMPLES = ''' resource_group: myResourceGroup name: myAzureFirewall state: absent - ''' RETURN = ''' @@ -314,15 +341,8 @@ id: import time import json -import re 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 copy import deepcopy -try: - from msrestazure.azure_exceptions import CloudError -except ImportError: - # This is handled in azure_rm_common - pass class Actions: @@ -350,6 +370,7 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): ), application_rule_collections=dict( type='list', + elements='dict', disposition='/properties/applicationRuleCollections', options=dict( priority=dict( @@ -365,6 +386,7 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): ), rules=dict( type='list', + elements='raw', disposition='properties/*', options=dict( name=dict( @@ -375,10 +397,12 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): ), source_addresses=dict( type='list', + elements='str', disposition='sourceAddresses' ), protocols=dict( type='list', + elements='dict', options=dict( type=dict( type='str', @@ -391,10 +415,12 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): ), target_fqdns=dict( type='list', + elements='raw', disposition='targetFqdns' ), fqdn_tags=dict( type='list', + elements='raw', disposition='fqdnTags' ) ) @@ -406,6 +432,7 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): ), nat_rule_collections=dict( type='list', + elements='dict', disposition='/properties/natRuleCollections', options=dict( priority=dict( @@ -421,6 +448,7 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): ), rules=dict( type='list', + elements='dict', disposition='properties/*', options=dict( name=dict( @@ -431,18 +459,22 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): ), source_addresses=dict( type='list', + elements='str', disposition='sourceAddresses' ), destination_addresses=dict( type='list', + elements='str', disposition='destinationAddresses' ), destination_ports=dict( type='list', + elements='str', disposition='destinationPorts' ), protocols=dict( - type='list' + type='list', + elements='raw' ), translated_address=dict( type='str', @@ -461,6 +493,7 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): ), network_rule_collections=dict( type='list', + elements='dict', disposition='/properties/networkRuleCollections', options=dict( priority=dict( @@ -476,6 +509,7 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): ), rules=dict( type='list', + elements='dict', disposition='properties/*', options=dict( name=dict( @@ -485,18 +519,22 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): type='str' ), protocols=dict( - type='list' + type='list', + elements='raw' ), source_addresses=dict( type='list', + elements='str', disposition='sourceAddresses' ), destination_addresses=dict( type='list', + elements='str', disposition='destinationAddresses' ), destination_ports=dict( type='list', + elements='str', disposition='destinationPorts' ) ) @@ -508,6 +546,7 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): ), ip_configurations=dict( type='list', + elements='dict', disposition='/properties/ipConfigurations', options=dict( subnet=dict( @@ -571,6 +610,7 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) resource_group = self.get_resource_group(self.resource_group) @@ -661,14 +701,14 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): self.status_code, 600, 30) - except CloudError as exc: + except Exception as exc: self.log('Error attempting to create the AzureFirewall instance.') self.fail('Error creating the AzureFirewall instance: {0}'.format(str(exc))) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: - response = {'text': response.text} + response = {'text': response.context['deserialized_data']} return response @@ -683,7 +723,7 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): self.status_code, 600, 30) - except CloudError as e: + except Exception as e: self.log('Error attempting to delete the AzureFirewall instance.') self.fail('Error deleting the AzureFirewall instance: {0}'.format(str(e))) @@ -701,11 +741,11 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): self.status_code, 600, 30) - response = json.loads(response.text) + response = json.loads(response.body()) found = True self.log("Response : {0}".format(response)) # self.log("AzureFirewall instance : {0} found".format(response.name)) - except CloudError as e: + except Exception as e: self.log('Did not find the AzureFirewall instance.') if found is True: return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_azurefirewall_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_azurefirewall_info.py index be6b08a36..d86932693 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_azurefirewall_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_azurefirewall_info.py @@ -41,7 +41,6 @@ EXAMPLES = ''' azure_rm_azurefirewall_info: resource_group: myResourceGroup name: myAzureFirewall - ''' RETURN = ''' @@ -102,16 +101,9 @@ firewalls: ''' -import time import json from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_rest import GenericRestClient -from copy import deepcopy -try: - from msrestazure.azure_exceptions import CloudError -except Exception: - # handled in azure_rm_common - pass class AzureRMAzureFirewallsInfo(AzureRMModuleBase): @@ -148,6 +140,7 @@ class AzureRMAzureFirewallsInfo(AzureRMModuleBase): setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if (self.resource_group is not None and self.name is not None): @@ -183,9 +176,9 @@ class AzureRMAzureFirewallsInfo(AzureRMModuleBase): self.status_code, 600, 30) - results = json.loads(response.text) + results = json.loads(response.body()) # self.log('Response : {0}'.format(response)) - except CloudError as e: + except Exception as e: self.log('Could not get info for @(Model.ModuleOperationNameUpper).') return self.format_item(results) @@ -213,9 +206,9 @@ class AzureRMAzureFirewallsInfo(AzureRMModuleBase): self.status_code, 600, 30) - results = json.loads(response.text) + results = json.loads(response.body()) # self.log('Response : {0}'.format(response)) - except CloudError as e: + except Exception as e: self.log('Could not get info for @(Model.ModuleOperationNameUpper).') return [self.format_item(x) for x in results['value']] if results['value'] else [] @@ -240,25 +233,31 @@ class AzureRMAzureFirewallsInfo(AzureRMModuleBase): self.status_code, 600, 30) - results = json.loads(response.text) + results = json.loads(response.body()) # self.log('Response : {0}'.format(response)) - except CloudError as e: + except Exception as e: self.log('Could not get info for @(Model.ModuleOperationNameUpper).') return [self.format_item(x) for x in results['value']] if results['value'] else [] def format_item(self, item): + if item is None or item == {}: + return {} d = { - 'id': item['id'], - 'name': item['name'], - 'location': item['location'], - 'etag': item['etag'], + 'id': item.get('id'), + 'name': item.get('name'), + 'location': item.get('location'), + 'etag': item.get('etag'), 'tags': item.get('tags'), - 'nat_rule_collections': item['properties']['natRuleCollections'], - 'network_rule_collections': item['properties']['networkRuleCollections'], - 'ip_configurations': item['properties']['ipConfigurations'], - 'provisioning_state': item['properties']['provisioningState'] + 'nat_rule_collections': dict(), + 'network_rule_collections': dict(), + 'ip_configurations': dict(), } + if isinstance(item.get('properties'), dict): + d['nat_rule_collections'] = item.get('properties').get('natRuleCollections') + d['network_rule_collections'] = item.get('properties').get('networkRuleCollections') + d['ip_configurations'] = item.get('properties').get('ipConfigurations') + d['provisioning_state'] = item.get('properties').get('provisioningState') return d diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backupazurevm.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backupazurevm.py index 25e9870d9..77d6d92ed 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backupazurevm.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backupazurevm.py @@ -74,40 +74,40 @@ author: EXAMPLES = \ ''' - - name: Enabling/Updating protection for the Azure VM - azure_rm_backupazurevm: - resource_group: 'myResourceGroup' - recovery_vault_name: 'testVault' - resource_id: '/subscriptions/00000000-0000-0000-0000-000000000000/ \ - resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/testVM' - backup_policy_id: '/subscriptions/00000000-0000-0000-0000-000000000000/ \ - resourceGroups/myResourceGroup/providers/microsoft.recoveryservices/vaults/testVault/backupPolicies/ProdPolicy' - state: 'create' - - name: Stop protection but retain existing data - azure_rm_backupazurevm: - resource_group: 'myResourceGroup' - recovery_vault_name: 'testVault' - resource_id: '/subscriptions/00000000-0000-0000-0000-000000000000/ \ - resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/testVM' - state: 'stop' - - name: Stop protection and delete data - azure_rm_backupazurevm: - resource_group: 'myResourceGroup' - recovery_vault_name: 'testVault' - resource_id: '/subscriptions/00000000-0000-0000-0000-000000000000/ \ - resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/testVM' - state: 'delete' - - name: Trigger an on-demand backup for a protected Azure VM - azure_rm_backupazurevm: - resource_group: 'myResourceGroup' - recovery_vault_name: 'testVault' - resource_id: '/subscriptions/00000000-0000-0000-0000-000000000000/ \ - resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/testVM' - backup_policy_id: '/subscriptions/00000000-0000-0000-0000-000000000000/ \ - resourceGroups/myResourceGroup/providers/microsoft.recoveryservices/vaults/testVault/backupPolicies/ProdPolicy' - recovery_point_expiry_time: '2023-02-09T06:00:00Z' - state: 'backup' - ''' +- name: Enabling/Updating protection for the Azure VM + azure_rm_backupazurevm: + resource_group: 'myResourceGroup' + recovery_vault_name: 'testVault' + resource_id: '/subscriptions/00000000-0000-0000-0000-000000000000/ \ + resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/testVM' + backup_policy_id: '/subscriptions/00000000-0000-0000-0000-000000000000/ \ + resourceGroups/myResourceGroup/providers/microsoft.recoveryservices/vaults/testVault/backupPolicies/ProdPolicy' + state: 'create' +- name: Stop protection but retain existing data + azure_rm_backupazurevm: + resource_group: 'myResourceGroup' + recovery_vault_name: 'testVault' + resource_id: '/subscriptions/00000000-0000-0000-0000-000000000000/ \ + resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/testVM' + state: 'stop' +- name: Stop protection and delete data + azure_rm_backupazurevm: + resource_group: 'myResourceGroup' + recovery_vault_name: 'testVault' + resource_id: '/subscriptions/00000000-0000-0000-0000-000000000000/ \ + resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/testVM' + state: 'delete' +- name: Trigger an on-demand backup for a protected Azure VM + azure_rm_backupazurevm: + resource_group: 'myResourceGroup' + recovery_vault_name: 'testVault' + resource_id: '/subscriptions/00000000-0000-0000-0000-000000000000/ \ + resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/testVM' + backup_policy_id: '/subscriptions/00000000-0000-0000-0000-000000000000/ \ + resourceGroups/myResourceGroup/providers/microsoft.recoveryservices/vaults/testVault/backupPolicies/ProdPolicy' + recovery_point_expiry_time: '2023-02-09T06:00:00Z' + state: 'backup' +''' RETURN = \ ''' @@ -121,9 +121,7 @@ id: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_rest import GenericRestClient from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt -import re import json -import time class Actions: @@ -186,8 +184,11 @@ class BackupAzureVM(AzureRMModuleBaseExt): return '2019-05-13' if self.state == 'create' or self.state == 'update' or self.state == 'delete' or self.state == 'stop' else '2016-12-01' def get_url(self): + sub_id = self.subscription_id + if self.module.params.get('subscription_id'): + sub_id = self.module.params.get('subscription_id') if self.state == 'create' or self.state == 'update' or self.state == 'delete' or self.state == 'stop': - return '/subscriptions' + '/' + self.subscription_id \ + return '/subscriptions' + '/' + sub_id \ + '/resourceGroups' + '/' + self.resource_group + '/providers' \ + '/Microsoft.RecoveryServices' + '/vaults' + '/' \ + self.recovery_vault_name \ @@ -197,7 +198,7 @@ class BackupAzureVM(AzureRMModuleBaseExt): + 'vm;iaasvmcontainerv2;' + self.parse_resource_to_dict(self.resource_id)['resource_group'] + ';' \ + self.parse_resource_to_dict(self.resource_id)['name'] if self.state == 'backup': - return '/subscriptions' + '/' + self.subscription_id \ + return '/subscriptions' + '/' + sub_id \ + '/resourceGroups' + '/' + self.resource_group + '/providers' \ + '/Microsoft.RecoveryServices' + '/vaults' + '/' \ + self.recovery_vault_name \ @@ -254,6 +255,7 @@ class BackupAzureVM(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) changed = False @@ -295,9 +297,9 @@ class BackupAzureVM(AzureRMModuleBaseExt): 'Error in creating/updating protection for Azure VM {0}'.format(str(e))) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: - response = {'text': response.text} + response = {'text': response.context['deserialized_data']} return response @@ -321,9 +323,9 @@ class BackupAzureVM(AzureRMModuleBaseExt): self.fail('Error in disabling the protection: {0}'.format(str(e))) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: - response = {'text': response.text} + response = {'text': response.context['deserialized_data']} return response @@ -347,9 +349,9 @@ class BackupAzureVM(AzureRMModuleBaseExt): self.fail('Error deleting the azure backup: {0}'.format(str(e))) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: - response = {'text': response.text} + response = {'text': response.context['deserialized_data']} return response @@ -374,9 +376,9 @@ class BackupAzureVM(AzureRMModuleBaseExt): 'Error while taking on-demand backup: {0}'.format(str(e))) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: - response = {'text': response.text} + response = {'text': response.context['deserialized_data']} return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backupazurevm_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backupazurevm_info.py index b8ad0cc8a..b4ba22fc1 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backupazurevm_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backupazurevm_info.py @@ -42,13 +42,13 @@ author: EXAMPLES = \ ''' - - name: Get Recovery Point Details - azure_rm_backupazurevm_info: - resource_group: 'myResourceGroup' - recovery_vault_name: 'testVault' - resource_id: '/subscriptions/00000000-0000-0000-0000-000000000000/ \ - resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/testVM' - ''' +- name: Get Recovery Point Details + azure_rm_backupazurevm_info: + resource_group: 'myResourceGroup' + recovery_vault_name: 'testVault' + resource_id: '/subscriptions/00000000-0000-0000-0000-000000000000/ \ + resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/testVM' +''' RETURN = \ ''' @@ -62,9 +62,7 @@ id: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_rest import GenericRestClient from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt -import re import json -import time class Actions: @@ -132,6 +130,7 @@ class BackupAzureVMInfo(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) response = self.get_recovery_point_info() @@ -158,9 +157,9 @@ class BackupAzureVMInfo(AzureRMModuleBaseExt): self.fail('Error in fetching recovery point {0}'.format(str(e))) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: - response = {'text': response.text} + response = {'text': response.context['deserialized_data']} return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backuppolicy.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backuppolicy.py index 7ec699566..4c1f6cca9 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backuppolicy.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backuppolicy.py @@ -103,43 +103,42 @@ author: ''' EXAMPLES = ''' - - name: Delete a backup policy - azure_rm_backuppolicy: - vault_name: Vault_Name - name: Policy_Name - resource_group: Resource_Group_Name - state: absent - - - name: Create a daily VM backup policy - azure_rm_backuppolicy: - vault_name: Vault_Name - name: Policy_Name - resource_group: Resource_Group_Name - state: present - backup_management_type: "AzureIaasVM" - schedule_run_frequency: "Daily" - instant_recovery_snapshot_retention: 2 - daily_retention_count: 12 - time_zone: "Pacific Standard Time" - schedule_run_time: 14 - - - name: Create a weekly VM backup policy - azure.azcollection.azure_rm_backuppolicy: - vault_name: Vault_Name - name: Policy_Name - resource_group: Resource_Group_Name - state: present - backup_management_type: "AzureIaasVM" - schedule_run_frequency: "Weekly" - instant_recovery_snapshot_retention: 5 - weekly_retention_count: 4 - schedule_days: - - "Monday" - - "Wednesday" - - "Friday" - time_zone: "Pacific Standard Time" - schedule_run_time: 8 - +- name: Delete a backup policy + azure_rm_backuppolicy: + vault_name: Vault_Name + name: Policy_Name + resource_group: Resource_Group_Name + state: absent + +- name: Create a daily VM backup policy + azure_rm_backuppolicy: + vault_name: Vault_Name + name: Policy_Name + resource_group: Resource_Group_Name + state: present + backup_management_type: "AzureIaasVM" + schedule_run_frequency: "Daily" + instant_recovery_snapshot_retention: 2 + daily_retention_count: 12 + time_zone: "Pacific Standard Time" + schedule_run_time: 14 + +- name: Create a weekly VM backup policy + azure.azcollection.azure_rm_backuppolicy: + vault_name: Vault_Name + name: Policy_Name + resource_group: Resource_Group_Name + state: present + backup_management_type: "AzureIaasVM" + schedule_run_frequency: "Weekly" + instant_recovery_snapshot_retention: 5 + weekly_retention_count: 4 + schedule_days: + - "Monday" + - "Wednesday" + - "Friday" + time_zone: "Pacific Standard Time" + schedule_run_time: 8 ''' RETURN = ''' @@ -169,7 +168,6 @@ type: sample: Microsoft.RecoveryServices/vaults/backupPolicies ''' -import uuid from datetime import datetime from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backuppolicy_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backuppolicy_info.py index d4a086766..ddebb2862 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backuppolicy_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backuppolicy_info.py @@ -45,12 +45,12 @@ author: ''' EXAMPLES = ''' - - name: Get backup policy information - azure_rm_backuppolicy_info: - vault_name: Vault_Name - name: Policy_Name - resource_group: Resource_Group_Name - register: backup_policy +- name: Get backup policy information + azure_rm_backuppolicy_info: + vault_name: Vault_Name + name: Policy_Name + resource_group: Resource_Group_Name + register: backup_policy ''' RETURN = ''' @@ -80,8 +80,6 @@ type: sample: Microsoft.RecoveryServices/vaults/backupPolicies ''' -import uuid -from datetime import datetime from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_bastionhost.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_bastionhost.py index c6b8e0d4d..29369a463 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_bastionhost.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_bastionhost.py @@ -139,12 +139,12 @@ EXAMPLES = ''' private_ip_allocation_method: Dynamic sku: name: Standard - enable_tunneling: False - enable_shareable_link: False - enable_ip_connect: False - enable_file_copy: False + enable_tunneling: false + enable_shareable_link: false + enable_ip_connect: false + enable_file_copy: false scale_units: 6 - disable_copy_paste: False + disable_copy_paste: false tags: key1: value1 @@ -153,7 +153,6 @@ EXAMPLES = ''' name: bastion-name resource_group: myResourceGroup state: absent - ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_batchaccount.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_batchaccount.py index afb4d3d51..ac237294c 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_batchaccount.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_batchaccount.py @@ -49,6 +49,7 @@ options: - It can be the storage account ID. Fox example "/subscriptions/{subscription_id}/resourceGroups/ {resource_group}/providers/Microsoft.Storage/storageAccounts/{name}". - It can be a dict which contains I(name) and I(resource_group) of the storage account. + type: raw key_vault: description: - Existing key vault with which to associate the Batch Account. @@ -56,6 +57,7 @@ options: - It can be the key vault ID. For example "/subscriptions/{subscription_id}/resourceGroups/ {resource_group}/providers/Microsoft.KeyVault/vaults/{name}". - It can be a dict which contains I(name) and I(resource_group) of the key vault. + type: raw pool_allocation_mode: description: - The pool acclocation mode of the Batch Account. @@ -83,14 +85,14 @@ author: ''' EXAMPLES = ''' - - name: Create Batch Account - azure_rm_batchaccount: - resource_group: MyResGroup - name: mybatchaccount - location: eastus - auto_storage_account: - name: mystorageaccountname - pool_allocation_mode: batch_service +- name: Create Batch Account + azure_rm_batchaccount: + resource_group: MyResGroup + name: mybatchaccount + location: eastus + auto_storage_account: + name: mystorageaccountname + pool_allocation_mode: batch_service ''' RETURN = ''' @@ -108,17 +110,13 @@ account_endpoint: sample: sampleacct.westus.batch.azure.com ''' -import time -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import normalize_location_name from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt from ansible.module_utils.common.dict_transformations import _snake_to_camel try: - from msrestazure.azure_exceptions import CloudError - from msrest.polling import LROPoller - from msrestazure.azure_operation import AzureOperationPoller - from msrest.serialization import Model + from azure.core.polling import LROPoller from azure.mgmt.batch import BatchManagementClient + from azure.core.exceptions import ResourceNotFoundError except ImportError: # This is handled in azure_rm_common pass @@ -172,7 +170,6 @@ class AzureRMBatchAccount(AzureRMModuleBaseExt): self.resource_group = None self.name = None self.batch_account = dict() - self.tags = None self.results = dict(changed=False) self.mgmt_client = None @@ -215,7 +212,8 @@ class AzureRMBatchAccount(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(BatchManagementClient, - base_url=self._cloud_environment.endpoints.resource_manager) + base_url=self._cloud_environment.endpoints.resource_manager, + is_track2=True) old_response = self.get_batchaccount() @@ -232,7 +230,13 @@ class AzureRMBatchAccount(AzureRMModuleBaseExt): elif self.state == 'present': self.results['old'] = old_response self.results['new'] = self.batch_account - if not self.idempotency_check(old_response, self.batch_account): + + update_tags, self.tags = self.update_tags(old_response['tags']) + + 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: self.to_do = Actions.Update if (self.to_do == Actions.Create) or (self.to_do == Actions.Update): @@ -275,17 +279,17 @@ class AzureRMBatchAccount(AzureRMModuleBaseExt): try: if self.to_do == Actions.Create: - response = self.mgmt_client.batch_account.create(resource_group_name=self.resource_group, - account_name=self.name, - parameters=self.batch_account) + response = self.mgmt_client.batch_account.begin_create(resource_group_name=self.resource_group, + account_name=self.name, + parameters=self.batch_account) else: response = self.mgmt_client.batch_account.update(resource_group_name=self.resource_group, account_name=self.name, - tags=self.tags, - auto_storage=self.batch_account.get('auto_storage')) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + parameters=dict(tags=self.tags, + auto_storage=self.batch_account.get('self.batch_account'))) + if isinstance(response, LROPoller): response = self.get_poller_result(response) - except CloudError as exc: + except Exception as exc: self.log('Error attempting to create the Batch Account instance.') self.fail("Error creating the Batch Account instance: {0}".format(str(exc))) return response.as_dict() @@ -298,13 +302,13 @@ class AzureRMBatchAccount(AzureRMModuleBaseExt): ''' self.log("Deleting the Batch Account instance {0}".format(self.name)) try: - response = self.mgmt_client.batch_account.delete(resource_group_name=self.resource_group, - account_name=self.name) - except CloudError as e: + response = self.mgmt_client.batch_account.begin_delete(resource_group_name=self.resource_group, + account_name=self.name) + except Exception as e: self.log('Error attempting to delete the Batch Account instance.') self.fail("Error deleting the Batch Account instance: {0}".format(str(e))) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) return True @@ -321,12 +325,30 @@ class AzureRMBatchAccount(AzureRMModuleBaseExt): found = True self.log("Response : {0}".format(response)) self.log("Batch Account instance : {0} found".format(response.name)) - except CloudError as e: - self.log('Did not find the Batch Account instance.') + except ResourceNotFoundError as e: + self.log('Did not find the Batch Account instance. Exception as {0}'.format(e)) if found is True: - return response.as_dict() + return self.format_item(response.as_dict()) return False + def format_item(self, item): + result = { + 'id': item['id'], + 'name': item['name'], + 'type': item['type'], + 'location': item['location'], + 'account_endpoint': item['account_endpoint'], + 'provisioning_state': item['provisioning_state'], + 'pool_allocation_mode': item['pool_allocation_mode'], + 'auto_storage': item['auto_storage'], + 'dedicated_core_quota': item['dedicated_core_quota'], + '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') + } + return result + def main(): """Main execution""" diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_batchaccount_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_batchaccount_info.py new file mode 100644 index 000000000..fb61248e4 --- /dev/null +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_batchaccount_info.py @@ -0,0 +1,196 @@ +#!/usr/bin/python +# +# Copyright (c) 2023 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_batchaccount_info +version_added: "0.1.2" +short_description: Get the Batch Account on Azure facts +description: + - Get the Batch Account on Azure facts. + +options: + resource_group: + description: + - The name of the resource group in which to create the Batch Account. + type: str + name: + description: + - The name of the Batch Account. + 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 Batch Account by name + azure_rm_batchaccount_info: + resource_group: MyResGroup + name: mybatchaccount + +- name: List the Batch Account by subscription + azure_rm_batchaccount_info: + tags: + - key1 +''' + +RETURN = ''' +id: + description: + - The ID of the Batch account. + returned: always + type: str + sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Batch/batchAccounts/sampleacct" +account_endpoint: + description: + - The account endpoint used to interact with the Batch service. + returned: always + type: str + sample: sampleacct.westus.batch.azure.com +''' + +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt + +try: + from azure.core.exceptions import ResourceNotFoundError + from azure.mgmt.batch import BatchManagementClient +except ImportError: + # This is handled in azure_rm_common + pass + + +class AzureRMBatchAccountInfo(AzureRMModuleBaseExt): + """Configuration class for an Azure RM Batch Account resource""" + + def __init__(self): + self.module_arg_spec = dict( + resource_group=dict( + type='str', + ), + name=dict( + type='str', + ), + tags=dict( + type='list', + elements='str' + ) + ) + + self.resource_group = None + self.name = None + self.tags = None + + self.results = dict(changed=False) + self.mgmt_client = None + + super(AzureRMBatchAccountInfo, 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()) + ['tags']: + setattr(self, key, kwargs[key]) + + response = [] + + self.mgmt_client = self.get_mgmt_svc_client(BatchManagementClient, + base_url=self._cloud_environment.endpoints.resource_manager, + is_track2=True) + + if self.resource_group is not None and self.name is not None: + response = [self.get_batchaccount()] + elif self.resource_group is not None: + response = self.list_by_resourcegroup() + else: + response = self.list_all() + + self.results['batch_account'] = [self.format_item(item) for item in response if item and self.has_tags(item.get('tags'), self.tags)] + + return self.results + + def list_by_resourcegroup(self): + self.log("List all Batch Account in the rsource group {0}".format(self.resource_group)) + result = [] + response = [] + try: + response = self.mgmt_client.batch_account.list_by_resource_group(resource_group_name=self.resource_group) + self.log("Response : {0}".format(response)) + except Exception as e: + self.log('Did not find the Batch Account instance. Exception as {0}'.format(e)) + for item in response: + result.append(item.as_dict()) + return result + + def list_all(self): + self.log("List all Batch Account in the same subscritpion") + result = [] + response = [] + try: + response = self.mgmt_client.batch_account.list() + self.log("Response : {0}".format(response)) + except Exception as e: + self.log('Did not find the Batch Account instance.') + for item in response: + result.append(item.as_dict()) + return result + + def get_batchaccount(self): + ''' + Gets the properties of the specified Batch Account + :return: deserialized Batch Account instance state dictionary + ''' + self.log("Checking if the Batch Account instance {0} is present".format(self.name)) + try: + response = self.mgmt_client.batch_account.get(resource_group_name=self.resource_group, + account_name=self.name) + self.log("Response : {0}".format(response)) + self.log("Batch Account instance : {0} found".format(response.name)) + except ResourceNotFoundError as e: + self.log('Did not find the Batch Account instance.') + return + return response.as_dict() + + def format_item(self, item): + result = { + 'id': item['id'], + 'name': item['name'], + 'type': item['type'], + 'location': item['location'], + 'account_endpoint': item['account_endpoint'], + 'provisioning_state': item['provisioning_state'], + 'pool_allocation_mode': item['pool_allocation_mode'], + 'auto_storage': item['auto_storage'], + 'dedicated_core_quota': item['dedicated_core_quota'], + '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') + } + return result + + +def main(): + """Main execution""" + AzureRMBatchAccountInfo() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnendpoint.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnendpoint.py index c289ad0fe..2f3a3d76f 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnendpoint.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnendpoint.py @@ -20,13 +20,16 @@ options: description: - Name of a resource group where the Azure CDN endpoint exists or will be created. required: true + type: str name: description: - Name of the Azure CDN endpoint. required: true + type: str location: description: - Valid azure location. Defaults to location of the resource group. + type: str started: description: - Use with I(state=present) to start the endpoint. @@ -45,19 +48,25 @@ options: description: - Name of the CDN profile where the endpoint attached to. required: true + type: str origins: description: - Set of source of the content being delivered via CDN. + - Required when creating. + elements: dict + type: list suboptions: name: description: - Origin name. required: true + type: str host_name: description: - The address of the origin. - It can be a domain name, IPv4 address, or IPv6 address. required: true + type: str http_port: description: - The value of the HTTP port. Must be between C(1) and C(65535). @@ -66,7 +75,6 @@ options: description: - The value of the HTTPS port. Must be between C(1) and C(65535). type: int - required: true origin_host_header: description: - The host header value sent to the origin with each request. @@ -111,6 +119,7 @@ options: description: - Assert the state of the Azure CDN endpoint. Use C(present) to create or update a Azure CDN endpoint and C(absent) to delete it. default: present + type: str choices: - absent - present @@ -124,24 +133,24 @@ author: ''' EXAMPLES = ''' - - name: Create a Azure CDN endpoint - azure_rm_cdnendpoint: - resource_group: myResourceGroup - profile_name: myProfile - name: myEndpoint - origins: - - name: TestOrig - host_name: "www.example.com" - tags: - testing: testing - delete: on-exit - foo: bar - - name: Delete a Azure CDN endpoint - azure_rm_cdnendpoint: - resource_group: myResourceGroup - profile_name: myProfile - name: myEndpoint - state: absent +- name: Create a Azure CDN endpoint + azure_rm_cdnendpoint: + resource_group: myResourceGroup + profile_name: myProfile + name: myEndpoint + origins: + - name: TestOrig + host_name: "www.example.com" + tags: + testing: testing + delete: on-exit + foo: bar +- name: Delete a Azure CDN endpoint + azure_rm_cdnendpoint: + resource_group: myResourceGroup + profile_name: myProfile + name: myEndpoint + state: absent ''' RETURN = ''' state: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnendpoint_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnendpoint_info.py index 897071eb9..9f89408d0 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnendpoint_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnendpoint_info.py @@ -24,13 +24,16 @@ options: description: - Name of resource group where this CDN profile belongs to. required: true + type: str profile_name: description: - Name of CDN profile. required: true + type: str name: description: - Limit results to a specific Azure CDN endpoint. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -46,19 +49,19 @@ author: ''' EXAMPLES = ''' - - name: Get facts for all endpoints in CDN profile - azure_rm_cdnendpoint_info: - resource_group: myResourceGroup - profile_name: myCDNProfile - tags: - - key - - key:value - - - name: Get facts of specific CDN endpoint - azure_rm_cdnendpoint_info: - resource_group: myResourceGroup - profile_name: myCDNProfile - name: myEndpoint1 +- name: Get facts for all endpoints in CDN profile + azure_rm_cdnendpoint_info: + resource_group: myResourceGroup + profile_name: myCDNProfile + tags: + - key + - key:value + +- name: Get facts of specific CDN endpoint + azure_rm_cdnendpoint_info: + resource_group: myResourceGroup + profile_name: myCDNProfile + name: myEndpoint1 ''' RETURN = ''' @@ -149,6 +152,7 @@ cdnendpoints: "https_port": null, "name": "xxxxxxxx-blob-core-windows-net" } + type: dict origin_host_header: description: - The host header value sent to the origin with each request. @@ -170,8 +174,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.mgmt.cdn import CdnManagementClient - from azure.mgmt.cdn.models import ErrorResponseException - from azure.common import AzureHttpError except ImportError: # handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnprofile.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnprofile.py index 012a9cba8..96761228f 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnprofile.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnprofile.py @@ -20,17 +20,21 @@ options: description: - Name of a resource group where the CDN profile exists or will be created. required: true + type: str name: description: - Name of the CDN profile. required: true + type: str location: description: - Valid Azure location. Defaults to location of the resource group. + type: str sku: description: - The pricing tier, defines a CDN provider, feature list and rate of the CDN profile. - Detailed pricing can be find at U(https://azure.microsoft.com/en-us/pricing/details/cdn/). + type: str choices: - standard_verizon - premium_verizon @@ -42,6 +46,7 @@ options: description: - Assert the state of the CDN profile. Use C(present) to create or update a CDN profile and C(absent) to delete it. default: present + type: str choices: - absent - present @@ -56,19 +61,19 @@ author: ''' EXAMPLES = ''' - - name: Create a CDN profile - azure_rm_cdnprofile: - resource_group: myResourceGroup - name: myCDN - sku: standard_akamai - tags: - testing: testing - - - name: Delete the CDN profile - azure_rm_cdnprofile: - resource_group: myResourceGroup - name: myCDN - state: absent +- name: Create a CDN profile + azure_rm_cdnprofile: + resource_group: myResourceGroup + name: myCDN + sku: standard_akamai + tags: + testing: testing + +- name: Delete the CDN profile + azure_rm_cdnprofile: + resource_group: myResourceGroup + name: myCDN + state: absent ''' RETURN = ''' id: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnprofile_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnprofile_info.py index 0a0e7c9c9..92b9b7957 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnprofile_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnprofile_info.py @@ -23,9 +23,11 @@ options: name: description: - Limit results to a specific CDN profile. + type: str resource_group: description: - The resource group to search for the desired CDN profile. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -41,18 +43,18 @@ author: ''' EXAMPLES = ''' - - name: Get facts for one CDN profile - azure_rm_cdnprofile_info: - name: Testing - resource_group: myResourceGroup +- name: Get facts for one CDN profile + azure_rm_cdnprofile_info: + name: Testing + resource_group: myResourceGroup - - name: Get facts for all CDN profiles - azure_rm_cdnprofile_info: +- name: Get facts for all CDN profiles + azure_rm_cdnprofile_info: - - name: Get facts by tags - azure_rm_cdnprofile_info: - tags: - - Environment:Test +- name: Get facts by tags + azure_rm_cdnprofile_info: + tags: + - Environment:Test ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cognitivesearch.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cognitivesearch.py index 037cee7f1..a8852c583 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cognitivesearch.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cognitivesearch.py @@ -116,10 +116,10 @@ author: ''' EXAMPLES = ''' - - name: Create Azure Cognitive Search - azure_rm_cognitivesearch: - resource_group: myResourceGroup - name: myAzureSearch +- name: Create Azure Cognitive Search + azure_rm_cognitivesearch: + resource_group: myResourceGroup + name: myAzureSearch ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cognitivesearch_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cognitivesearch_info.py index 4ae5cf819..261712dce 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cognitivesearch_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cognitivesearch_info.py @@ -38,17 +38,17 @@ author: ''' EXAMPLES = ''' - - name: Get Azure Cognitive Search info from resource group 'myResourceGroup' and name 'myAzureSearch' - azure_rm_cognitivesearch_info: - resource_group: myResourceGroup - name: myAzureSearch +- name: Get Azure Cognitive Search info from resource group 'myResourceGroup' and name 'myAzureSearch' + azure_rm_cognitivesearch_info: + resource_group: myResourceGroup + name: myAzureSearch - - name: Get Azure Cognitive Search info from resource group 'myResourceGroup' - azure_rm_cognitivesearch_info: - resource_group: myResourceGroup +- name: Get Azure Cognitive Search info from resource group 'myResourceGroup' + azure_rm_cognitivesearch_info: + resource_group: myResourceGroup - - name: Get all Azure Cognitive Search info - azure_rm_cognitivesearch_info: +- name: Get all Azure Cognitive Search info + azure_rm_cognitivesearch_info: ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerinstance.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerinstance.py index 2b0bffbc5..05df1ee8b 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerinstance.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerinstance.py @@ -63,6 +63,7 @@ options: - This option is deprecated, using I(ports) under I(containers)". type: list elements: int + default: [] location: description: - Valid azure location. Defaults to location of the resource group. @@ -249,82 +250,82 @@ author: ''' EXAMPLES = ''' - - name: Create sample container group - azure_rm_containerinstance: - resource_group: myResourceGroup - name: myContainerInstanceGroup - os_type: linux - ip_address: public - containers: - - name: myContainer1 - image: httpd - memory: 1.5 - ports: - - 80 - - 81 - - - name: Create sample container group with azure file share volume - azure_rm_containerinstance: - resource_group: myResourceGroup - name: myContainerInstanceGroupz - os_type: linux - ip_address: public - containers: - - name: mycontainer1 - image: httpd - memory: 1 - volume_mounts: - - name: filesharevolume - mount_path: "/data/files" - ports: - - 80 - - 81 - volumes: - - name: filesharevolume - azure_file: - storage_account_name: mystorageaccount - share_name: acishare - storage_account_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - - - name: Create sample container group with git repo volume - azure_rm_containerinstance: - resource_group: myResourceGroup - name: myContainerInstanceGroup - os_type: linux - ip_address: public - containers: - - name: mycontainer1 - image: httpd - memory: 1 - volume_mounts: - - name: myvolume1 - mount_path: "/mnt/test" - ports: - - 80 - - 81 - volumes: - - name: myvolume1 - git_repo: - repository: "https://github.com/Azure-Samples/aci-helloworld.git" - - - name: Create sample container instance with subnet - azure_rm_containerinstance: - resource_group: myResourceGroup - name: myContainerInstanceGroup - os_type: linux - ip_address: private - location: eastus - subnet_ids: - - "{{ subnet_id }}" - ports: - - 80 - containers: - - name: mycontainer1 - image: httpd - memory: 1.5 - ports: - - 80 - - 81 +- name: Create sample container group + azure_rm_containerinstance: + resource_group: myResourceGroup + name: myContainerInstanceGroup + os_type: linux + ip_address: public + containers: + - name: myContainer1 + image: httpd + memory: 1.5 + ports: + - 80 + - 81 + +- name: Create sample container group with azure file share volume + azure_rm_containerinstance: + resource_group: myResourceGroup + name: myContainerInstanceGroupz + os_type: linux + ip_address: public + containers: + - name: mycontainer1 + image: httpd + memory: 1 + volume_mounts: + - name: filesharevolume + mount_path: "/data/files" + ports: + - 80 + - 81 + volumes: + - name: filesharevolume + azure_file: + storage_account_name: mystorageaccount + share_name: acishare + storage_account_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + +- name: Create sample container group with git repo volume + azure_rm_containerinstance: + resource_group: myResourceGroup + name: myContainerInstanceGroup + os_type: linux + ip_address: public + containers: + - name: mycontainer1 + image: httpd + memory: 1 + volume_mounts: + - name: myvolume1 + mount_path: "/mnt/test" + ports: + - 80 + - 81 + volumes: + - name: myvolume1 + git_repo: + repository: "https://github.com/Azure-Samples/aci-helloworld.git" + +- name: Create sample container instance with subnet + azure_rm_containerinstance: + resource_group: myResourceGroup + name: myContainerInstanceGroup + os_type: linux + ip_address: private + location: eastus + subnet_ids: + - "{{ subnet_id }}" + ports: + - 80 + containers: + - name: mycontainer1 + image: httpd + memory: 1.5 + ports: + - 80 + - 81 ''' RETURN = ''' id: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerinstance_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerinstance_info.py index 3ad3b9722..9ef9b254c 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerinstance_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerinstance_info.py @@ -41,17 +41,17 @@ author: ''' EXAMPLES = ''' - - name: Get specific Container Instance facts - azure_rm_containerinstance_info: - resource_group: myResourceGroup - name: myContainer - - - name: List Container Instances in a specified resource group name - azure_rm_containerinstance_info: - resource_group: myResourceGroup - tags: - - key - - key:value +- name: Get specific Container Instance facts + azure_rm_containerinstance_info: + resource_group: myResourceGroup + name: myContainer + +- name: List Container Instances in a specified resource group name + azure_rm_containerinstance_info: + resource_group: myResourceGroup + tags: + - key + - key:value ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistry.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistry.py index cf974f378..ff94c537c 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistry.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistry.py @@ -63,22 +63,22 @@ author: ''' EXAMPLES = ''' - - name: Create an azure container registry - azure_rm_containerregistry: - name: myRegistry - location: eastus - resource_group: myResourceGroup - admin_user_enabled: true - sku: Premium - tags: - Release: beta1 - Environment: Production - - - name: Remove an azure container registry - azure_rm_containerregistry: - name: myRegistry - resource_group: myResourceGroup - state: absent +- name: Create an azure container registry + azure_rm_containerregistry: + name: myRegistry + location: eastus + resource_group: myResourceGroup + admin_user_enabled: true + sku: Premium + tags: + Release: beta1 + Environment: Production + +- name: Remove an azure container registry + azure_rm_containerregistry: + name: myRegistry + resource_group: myResourceGroup + state: absent ''' RETURN = ''' id: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistry_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistry_info.py index 8148674fa..8be247d37 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistry_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistry_info.py @@ -46,17 +46,17 @@ author: ''' EXAMPLES = ''' - - name: Get instance of Registry - azure_rm_containerregistry_info: - resource_group: myResourceGroup - name: myRegistry - - - name: List instances of Registry - azure_rm_containerregistry_info: - resource_group: myResourceGroup - tags: - - key - - key:value +- name: Get instance of Registry + azure_rm_containerregistry_info: + resource_group: myResourceGroup + name: myRegistry + +- name: List instances of Registry + azure_rm_containerregistry_info: + resource_group: myResourceGroup + tags: + - key + - key:value ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistryreplication.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistryreplication.py index 115d55c29..040214f03 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistryreplication.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistryreplication.py @@ -21,20 +21,34 @@ options: description: - The name of the resource group to which the container registry belongs. required: True + type: str registry_name: description: - The name of the container registry. required: True + type: str replication_name: description: - The name of the I(replication). required: True + type: str replication: description: - The parameters for creating a replication. + type: dict location: description: - Resource location. If not set, location from the resource group will be used as default. + type: str + state: + description: + - Assert the state of the Container registery replication. + - Use C(present) to create or update Container registery replication and C(absent) to delete it. + default: present + type: str + choices: + - absent + - present extends_documentation_fragment: - azure.azcollection.azure @@ -45,13 +59,13 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) Replication - azure_rm_containerregistryreplication: - resource_group: myResourceGroup - registry_name: myRegistry - replication_name: myReplication - replication: replication - location: eastus +- name: Create (or update) Replication + azure_rm_containerregistryreplication: + resource_group: myResourceGroup + registry_name: myRegistry + replication_name: myReplication + replication: replication + location: eastus ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistryreplication_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistryreplication_info.py index 123a83288..769910577 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistryreplication_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistryreplication_info.py @@ -21,14 +21,17 @@ options: description: - The name of the resource group to which the container registry belongs. required: True + type: str registry_name: description: - The name of the container registry. required: True + type: str replication_name: description: - The name of the replication. required: True + type: str extends_documentation_fragment: - azure.azcollection.azure @@ -39,11 +42,11 @@ author: ''' EXAMPLES = ''' - - name: Get instance of Replication - azure_rm_containerregistryreplication_info: - resource_group: resource_group_name - registry_name: registry_name - replication_name: replication_name +- name: Get instance of Replication + azure_rm_containerregistryreplication_info: + resource_group: resource_group_name + registry_name: registry_name + replication_name: replication_name ''' RETURN = ''' @@ -86,7 +89,6 @@ replications: - The status of the replication at the time the operation was called. returned: always type: complex - sample: status contains: message: description: @@ -98,7 +100,7 @@ replications: description: - The timestamp when the status was changed to the current value. returned: always - type: datetime + type: str sample: "2017-03-01T23:15:37.0707808Z" ''' @@ -106,7 +108,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError - from azure.core.polling import LROPoller except ImportError: # This is handled in azure_rm_common pass @@ -137,7 +138,7 @@ class AzureRMReplicationsFacts(AzureRMModuleBase): self.resource_group = None self.registry_name = None self.replication_name = None - super(AzureRMReplicationsFacts, self).__init__(self.module_arg_spec, supports_check_mode=True) + super(AzureRMReplicationsFacts, self).__init__(self.module_arg_spec, supports_tags=False, supports_check_mode=True) def exec_module(self, **kwargs): for key in self.module_arg_spec: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistrywebhook.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistrywebhook.py index 0175af3e6..cdc77d20c 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistrywebhook.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistrywebhook.py @@ -21,26 +21,33 @@ options: description: - The name of the resource group to which the container registry belongs. required: True + type: str registry_name: description: - The name of the container registry. required: True + type: str webhook_name: description: - The name of the webhook. required: True + type: str location: description: - Resource location. If not set, location from the resource group will be used as default. + type: str service_uri: description: - The service URI for the webhook to post notifications. + type: str custom_headers: description: - Custom headers that will be added to the webhook notifications. + type: dict status: description: - The status of the webhook at the time the operation was called. + type: str choices: - 'enabled' - 'disabled' @@ -48,10 +55,21 @@ options: description: - "The scope of repositories where the event can be triggered. For example, 'foo:*' means events for all tags under repository 'foo'. 'foo:bar' m eans events for 'foo:bar' only. 'foo' is equivalent to 'foo:latest'. Empty means all events." + type: str actions: description: - The list of actions that trigger the webhook to post notifications. type: list + elements: str + state: + description: + - Assert the state of the Container registery replication. + - Use C(present) to create or update Container registery replication and C(absent) to delete it. + default: present + type: str + choices: + - absent + - present extends_documentation_fragment: - azure.azcollection.azure @@ -62,12 +80,12 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) Webhook - azure_rm_containerregistrywebhook: - resource_group: myResourceGroup - registry_name: myRegistry - webhook_name: myWebhook - location: eastus +- name: Create (or update) Webhook + azure_rm_containerregistrywebhook: + resource_group: myResourceGroup + registry_name: myRegistry + webhook_name: myWebhook + location: eastus ''' RETURN = ''' @@ -150,7 +168,8 @@ class AzureRMWebhooks(AzureRMModuleBase): type='str' ), actions=dict( - type='list' + type='list', + elements='str' ), state=dict( type='str', diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistrywebhook_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistrywebhook_info.py index c15ed3ef3..379e072e0 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistrywebhook_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_containerregistrywebhook_info.py @@ -21,14 +21,17 @@ options: description: - The name of the resource group to which the container registry belongs. required: True + type: str registry_name: description: - The name of the container registry. required: True + type: str webhook_name: description: - The name of the webhook. required: True + type: str extends_documentation_fragment: - azure.azcollection.azure @@ -39,11 +42,11 @@ author: ''' EXAMPLES = ''' - - name: Get instance of Webhook - azure_rm_containerregistrywebhook_info: - resource_group: resource_group_name - registry_name: registry_name - webhook_name: webhook_name +- name: Get instance of Webhook + azure_rm_containerregistrywebhook_info: + resource_group: resource_group_name + registry_name: registry_name + webhook_name: webhook_name ''' RETURN = ''' @@ -136,7 +139,7 @@ class AzureRMWebhooksFacts(AzureRMModuleBase): self.resource_group = None self.registry_name = None self.webhook_name = None - super(AzureRMWebhooksFacts, self).__init__(self.module_arg_spec, supports_check_mode=True) + super(AzureRMWebhooksFacts, self).__init__(self.module_arg_spec, supports_tags=False, supports_check_mode=True) def exec_module(self, **kwargs): for key in self.module_arg_spec: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cosmosdbaccount.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cosmosdbaccount.py index b3066126d..d1f3dd987 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cosmosdbaccount.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cosmosdbaccount.py @@ -21,17 +21,21 @@ options: description: - Name of an Azure resource group. required: True + type: str name: description: - Cosmos DB database account name. required: True + type: str location: description: - The location of the resource group to which the resource belongs. - Required when I(state=present). + type: str kind: description: - Indicates the type of database account. This can only be set at database account creation. + type: str choices: - 'global_document_db' - 'mongo_db' @@ -39,11 +43,13 @@ options: consistency_policy: description: - The consistency policy for the Cosmos DB account. + type: dict suboptions: default_consistency_level: description: - The default consistency level and configuration settings of the Cosmos DB account. - Required when I(state=present). + type: str choices: - 'eventual' - 'session' @@ -65,20 +71,25 @@ options: - An array that contains the georeplication locations enabled for the Cosmos DB account. - Required when I(state=present). type: list + elements: dict suboptions: name: description: - The name of the region. + type: str + required: true failover_priority: description: - The failover priority of the region. A failover priority of 0 indicates a write region. - The maximum value for a failover priority = (total number of regions - 1). - Failover priority values must be unique for each of the regions in which the database account exists. type: int + required: true database_account_offer_type: description: - Database account offer type, for example I(Standard) - Required when I(state=present). + type: str enable_free_tier: description: - If enabled the account is free-tier. @@ -91,6 +102,7 @@ options: - In CIDR form to be included as the allowed list of client IPs for a given database account. - IP addresses/ranges must be comma separated and must not contain any spaces. - This value has been deprecated, and will be removed in a later version. Use I(ip_rules) instead. + type: str ip_rules: description: - The IP addresses or IP address ranges in CIDR form to be included as the allowed list of client IPs. @@ -137,11 +149,14 @@ options: description: - List of Virtual Network ACL rules configured for the Cosmos DB account. type: list + elements: dict suboptions: subnet: description: - It can be a string containing resource id of a subnet. - It can be a dictionary containing 'resource_group', 'virtual_network_name' and 'subnet_name' + type: raw + required: true ignore_missing_v_net_service_endpoint: description: - Create Cosmos DB account without existing virtual network service endpoint. @@ -151,13 +166,14 @@ options: - Enables the account to write in multiple locations type: bool state: - description: - - Assert the state of the Database Account. - - Use C(present) to create or update an Database Account and C(absent) to delete it. - default: present - choices: - - absent - - present + description: + - Assert the state of the Database Account. + - Use C(present) to create or update an Database Account and C(absent) to delete it. + default: present + type: str + choices: + - absent + - present extends_documentation_fragment: - azure.azcollection.azure @@ -169,36 +185,36 @@ author: ''' EXAMPLES = ''' - - name: Create Cosmos DB Account - min - azure_rm_cosmosdbaccount: - resource_group: myResourceGroup - name: myDatabaseAccount - location: westus - geo_rep_locations: - - name: southcentralus - failover_priority: 0 - database_account_offer_type: Standard - - - name: Create Cosmos DB Account - max - azure_rm_cosmosdbaccount: - resource_group: myResourceGroup - name: myDatabaseAccount - location: westus - kind: mongo_db - geo_rep_locations: - - name: southcentralus - failover_priority: 0 - database_account_offer_type: Standard - ip_rules: - - 10.10.10.10 - enable_multiple_write_locations: yes - virtual_network_rules: - - subnet: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVi - rtualNetwork/subnets/mySubnet" - consistency_policy: - default_consistency_level: bounded_staleness - max_staleness_prefix: 10 - max_interval_in_seconds: 1000 +- name: Create Cosmos DB Account - min + azure_rm_cosmosdbaccount: + resource_group: myResourceGroup + name: myDatabaseAccount + location: westus + geo_rep_locations: + - name: southcentralus + failover_priority: 0 + database_account_offer_type: Standard + +- name: Create Cosmos DB Account - max + azure_rm_cosmosdbaccount: + resource_group: myResourceGroup + name: myDatabaseAccount + location: westus + kind: mongo_db + geo_rep_locations: + - name: southcentralus + failover_priority: 0 + database_account_offer_type: Standard + ip_rules: + - 10.10.10.10 + enable_multiple_write_locations: true + virtual_network_rules: + - subnet: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVi + rtualNetwork/subnets/mySubnet" + consistency_policy: + default_consistency_level: bounded_staleness + max_staleness_prefix: 10 + max_interval_in_seconds: 1000 ''' RETURN = ''' @@ -217,7 +233,6 @@ from ansible.module_utils.common.dict_transformations import _snake_to_camel try: from azure.core.polling import LROPoller from azure.core.exceptions import ResourceNotFoundError - from msrestazure.azure_operation import AzureOperationPoller from azure.mgmt.cosmosdb import CosmosDBManagementClient from ansible.module_utils.six import string_types except ImportError: @@ -272,6 +287,7 @@ class AzureRMCosmosDBAccount(AzureRMModuleBase): ), geo_rep_locations=dict( type='list', + elements='dict', options=dict( name=dict( type='str', @@ -322,9 +338,10 @@ class AzureRMCosmosDBAccount(AzureRMModuleBase): ), virtual_network_rules=dict( type='list', + elements='dict', options=dict( - id=dict( - type='str', + subnet=dict( + type='raw', required=True ), ignore_missing_v_net_service_endpoint=dict( @@ -474,7 +491,7 @@ class AzureRMCosmosDBAccount(AzureRMModuleBase): response = self.mgmt_client.database_accounts.begin_create_or_update(resource_group_name=self.resource_group, account_name=self.name, create_update_parameters=self.parameters) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: @@ -493,7 +510,7 @@ class AzureRMCosmosDBAccount(AzureRMModuleBase): response = self.mgmt_client.database_accounts.begin_delete(resource_group_name=self.resource_group, account_name=self.name) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as e: self.log('Error attempting to delete the Database Account instance.') diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cosmosdbaccount_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cosmosdbaccount_info.py index c97b59ea7..61414272a 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cosmosdbaccount_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cosmosdbaccount_info.py @@ -20,9 +20,11 @@ options: resource_group: description: - Name of an Azure resource group. + type: str name: description: - Cosmos DB database account name. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -49,17 +51,17 @@ author: ''' EXAMPLES = ''' - - name: Get instance of Database Account - azure_rm_cosmosdbaccount_info: - resource_group: myResourceGroup - name: testaccount - - - name: List instances of Database Account - azure_rm_cosmosdbaccount_info: - resource_group: myResourceGroup - tags: - - key - - key:value +- name: Get instance of Database Account + azure_rm_cosmosdbaccount_info: + resource_group: myResourceGroup + name: testaccount + +- name: List instances of Database Account + azure_rm_cosmosdbaccount_info: + resource_group: myResourceGroup + tags: + - key + - key:value ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datafactory.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datafactory.py index 66e75f0c8..eabe176de 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datafactory.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datafactory.py @@ -114,7 +114,6 @@ EXAMPLES = ''' collaboration_branch: testbranch root_folder: "./" repository_name: vault - ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datafactory_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datafactory_info.py index cdd63d717..825afb67f 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datafactory_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datafactory_info.py @@ -46,19 +46,19 @@ author: ''' EXAMPLES = ''' - - name: Get data factory by name - azure_rm_datafactory_info: - resource_group: "{{ resource_group }}" - name: "{{ name }}" +- name: Get data factory by name + azure_rm_datafactory_info: + resource_group: "{{ resource_group }}" + name: "{{ name }}" - - name: Get data factory by resource group - azure_rm_datafactory_info: - resource_group: "{{ resource_group }}" +- name: Get data factory by resource group + azure_rm_datafactory_info: + resource_group: "{{ resource_group }}" - - name: Get data factory in relate subscription - azure_rm_datafactory_info: - tags: - - key1 +- name: Get data factory in relate subscription + azure_rm_datafactory_info: + tags: + - key1 ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datalakestore.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datalakestore.py index edce24665..eaecb9df5 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datalakestore.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datalakestore.py @@ -167,10 +167,10 @@ author: ''' EXAMPLES = ''' - - name: Create Azure Data Lake Store - azure_rm_datalakestore: - resource_group: myResourceGroup - name: myDataLakeStore +- name: Create Azure Data Lake Store + azure_rm_datalakestore: + resource_group: myResourceGroup + name: myDataLakeStore ''' RETURN = ''' @@ -417,7 +417,6 @@ state: ''' from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase -import datetime try: from azure.core.exceptions import ResourceNotFoundError @@ -472,7 +471,6 @@ class AzureRMDatalakeStore(AzureRMModuleBase): 'Commitment_500TB', 'Commitment_1PB', 'Commitment_5PB']), resource_group=dict(type='str', required=True, aliases=['resource_group_name']), state=dict(type='str', default='present', choices=['present', 'absent']), - tags=dict(type='dict'), virtual_network_rules=dict( type='list', elements='dict', @@ -484,7 +482,6 @@ class AzureRMDatalakeStore(AzureRMModuleBase): self.name = None self.resource_group = None self.location = None - self.tags = None self.new_tier = None self.default_group = None self.encryption_config = dict() @@ -504,7 +501,7 @@ class AzureRMDatalakeStore(AzureRMModuleBase): super(AzureRMDatalakeStore, self).__init__(derived_arg_spec=self.module_arg_spec, supports_check_mode=False, - supports_tags=False) + supports_tags=True) def exec_module(self, **kwargs): for key in list(self.module_arg_spec.keys()) + ['tags']: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datalakestore_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datalakestore_info.py index 842330cc0..2417ff74a 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datalakestore_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datalakestore_info.py @@ -37,17 +37,17 @@ author: ''' EXAMPLES = ''' - - name: Get Azure Data Lake Store info from resource group 'myResourceGroup' and name 'myDataLakeStore' - azure_rm_datalakestore_info: - resource_group: myResourceGroup - name: myDataLakeStore +- name: Get Azure Data Lake Store info from resource group 'myResourceGroup' and name 'myDataLakeStore' + azure_rm_datalakestore_info: + resource_group: myResourceGroup + name: myDataLakeStore - - name: Get Azure Data Lake Store info from resource group 'myResourceGroup' - azure_rm_datalakestore_info: - resource_group: myResourceGroup +- name: Get Azure Data Lake Store info from resource group 'myResourceGroup' + azure_rm_datalakestore_info: + resource_group: myResourceGroup - - name: Get Azure Data Lake Store info - azure_rm_datalakestore_info: +- name: Get Azure Data Lake Store info + azure_rm_datalakestore_info: ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_ddosprotectionplan.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_ddosprotectionplan.py index 0ae5e82f8..642248d29 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_ddosprotectionplan.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_ddosprotectionplan.py @@ -28,14 +28,14 @@ options: - Resource location. If not set, location from the resource group will be used as default. type: str state: - description: - - Assert the state of the DDoS protection plan. - - Use C(present) to create or update an DDoS protection plan and C(absent) to delete it. - type: str - default: present - choices: - - absent - - present + description: + - Assert the state of the DDoS protection plan. + - Use C(present) to create or update an DDoS protection plan and C(absent) to delete it. + type: str + default: present + choices: + - absent + - present log_path: description: - parent argument. @@ -87,7 +87,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError - from azure.mgmt.network import NetworkManagementClient except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_ddosprotectionplan_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_ddosprotectionplan_info.py index 70b37ac73..74eb190a3 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_ddosprotectionplan_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_ddosprotectionplan_info.py @@ -34,10 +34,10 @@ author: EXAMPLES = ''' - - name: Get facts of specific DDoS protection plan - azure_rm_ddosprotectionplan_info: - resource_group: myResourceGroup - name: myDDoSProtectionPlan +- name: Get facts of specific DDoS protection plan + azure_rm_ddosprotectionplan_info: + resource_group: myResourceGroup + name: myDDoSProtectionPlan ''' RETURN = ''' @@ -47,7 +47,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_deployment.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_deployment.py index 2b6a23a52..07cf93d8e 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_deployment.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_deployment.py @@ -21,67 +21,75 @@ description: - For more information on Azure Resource Manager templates see U(https://azure.microsoft.com/en-us/documentation/articles/resource-group-template-deploy/). options: - resource_group: - description: - - The resource group name to use or create to host the deployed template. - required: true - aliases: - - resource_group_name - name: - description: - - The name of the deployment to be tracked in the resource group deployment history. - - Re-using a deployment name will overwrite the previous value in the resource group's deployment history. - default: ansible-arm - aliases: - - deployment_name - location: - description: - - The geo-locations in which the resource group will be located. - default: westus - deployment_mode: - description: - - In incremental mode, resources are deployed without deleting existing resources that are not included in the template. - - In complete mode resources are deployed and existing resources in the resource group not included in the template are deleted. - default: incremental - choices: - - complete - - incremental - template: - description: - - A hash containing the templates inline. This parameter is mutually exclusive with I(template_link). - - Either I(template) or I(template_link) is required if I(state=present). - type: dict - template_link: - description: - - Uri of file containing the template body. This parameter is mutually exclusive with I(template). - - Either I(template) or I(template_link) is required if I(state=present). - parameters: - description: - - A hash of all the required template variables for the deployment template. This parameter is mutually exclusive with I(parameters_link). - - Either I(parameters_link) or I(parameters) is required if I(state=present). - type: dict - parameters_link: - description: - - Uri of file containing the parameters body. This parameter is mutually exclusive with I(parameters). - - Either I(parameters_link) or I(parameters) is required if I(state=present). - wait_for_deployment_completion: - description: - - Whether or not to block until the deployment has completed. - type: bool - default: 'yes' - wait_for_deployment_polling_period: - description: - - Time (in seconds) to wait between polls when waiting for deployment completion. - default: 10 - state: - description: - - If I(state=present), template will be created. - - If I(state=present) and deployment exists, it will be updated. - - If I(state=absent), the resource group will be removed. - default: present - choices: - - present - - absent + resource_group: + description: + - The resource group name to use or create to host the deployed template. + required: true + type: str + aliases: + - resource_group_name + name: + description: + - The name of the deployment to be tracked in the resource group deployment history. + - Re-using a deployment name will overwrite the previous value in the resource group's deployment history. + default: ansible-arm + type: str + aliases: + - deployment_name + location: + description: + - The geo-locations in which the resource group will be located. + default: westus + type: str + deployment_mode: + description: + - In incremental mode, resources are deployed without deleting existing resources that are not included in the template. + - In complete mode resources are deployed and existing resources in the resource group not included in the template are deleted. + default: incremental + type: str + choices: + - complete + - incremental + template: + description: + - A hash containing the templates inline. This parameter is mutually exclusive with I(template_link). + - Either I(template) or I(template_link) is required if I(state=present). + type: dict + template_link: + description: + - Uri of file containing the template body. This parameter is mutually exclusive with I(template). + - Either I(template) or I(template_link) is required if I(state=present). + type: str + parameters: + description: + - A hash of all the required template variables for the deployment template. This parameter is mutually exclusive with I(parameters_link). + - Either I(parameters_link) or I(parameters) is required if I(state=present). + type: dict + parameters_link: + description: + - Uri of file containing the parameters body. This parameter is mutually exclusive with I(parameters). + - Either I(parameters_link) or I(parameters) is required if I(state=present). + type: str + wait_for_deployment_completion: + description: + - Whether or not to block until the deployment has completed. + type: bool + default: true + wait_for_deployment_polling_period: + description: + - Time (in seconds) to wait between polls when waiting for deployment completion. + default: 10 + type: int + state: + description: + - If I(state=present), template will be created. + - If I(state=present) and deployment exists, it will be updated. + - If I(state=absent), the resource group will be removed. + default: present + type: str + choices: + - present + - absent extends_documentation_fragment: - azure.azcollection.azure @@ -394,7 +402,7 @@ deployment: outputs: description: - Dictionary of outputs received from the deployment. - type: complex + type: dict returned: always sample: { "hostname": { "type": "String", "value": "myvirtualmachine.eastus2.cloudapp.azure.com" } } ''' @@ -402,17 +410,12 @@ deployment: import time try: - from azure.common.credentials import ServicePrincipalCredentials import time - import yaml except ImportError as exc: IMPORT_ERROR = "Error importing module prerequisites: %s" % exc try: - from itertools import chain from azure.core.exceptions import ResourceNotFoundError - from azure.mgmt.resource.resources import ResourceManagementClient - from azure.mgmt.network import NetworkManagementClient except ImportError: # This is handled in azure_rm_common diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_deployment_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_deployment_info.py index 95dd56195..6fcaa1265 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_deployment_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_deployment_info.py @@ -21,9 +21,11 @@ options: description: - The name of the resource group. required: True + type: str name: description: - The name of the deployment. + type: str extends_documentation_fragment: - azure.azcollection.azure @@ -34,10 +36,10 @@ author: ''' EXAMPLES = ''' - - name: Get instance of Deployment - azure_rm_deployment_info: - resource_group: myResourceGroup - name: myDeployment +- name: Get instance of Deployment + azure_rm_deployment_info: + resource_group: myResourceGroup + name: myDeployment ''' RETURN = ''' @@ -58,31 +60,36 @@ deployments: - Resource group name. returned: always sample: myResourceGroup + type: str name: description: - Deployment name. returned: always + type: str sample: myDeployment provisioning_state: description: - Provisioning state of the deployment. returned: always + type: str sample: Succeeded template_link: description: - Link to the template. returned: always + type: str sample: "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/d01a5c06f4f1bc03a049ca17bbbd6e06d62657b3/101-vm-simple-linux/ azuredeploy.json" parameters: description: - Dictionary containing deployment parameters. returned: always - type: complex + type: dict outputs: description: - Dictionary containing deployment outputs. returned: always + type: dict output_resources: description: - List of resources. @@ -122,8 +129,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError - from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlab.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlab.py index 531cbf55a..1424be8c9 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlab.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlab.py @@ -21,16 +21,20 @@ options: description: - The name of the resource group. required: True + type: str name: description: - The name of the lab. required: True + type: str location: description: - The location of the resource. + type: str storage_type: description: - Type of storage used by the lab. It can be either C(premium) or C(standard). + type: str choices: - 'standard' - 'premium' @@ -39,13 +43,14 @@ options: - Allow creation of premium data disks. type: bool state: - description: - - Assert the state of the DevTest Lab. - - Use C(present) to create or update an DevTest Lab and C(absent) to delete it. - default: present - choices: - - absent - - present + description: + - Assert the state of the DevTest Lab. + - Use C(present) to create or update an DevTest Lab and C(absent) to delete it. + default: present + type: str + choices: + - absent + - present extends_documentation_fragment: - azure.azcollection.azure @@ -57,11 +62,11 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) DevTest Lab - azure_rm_devtestlab: - resource_group: myResourceGroup - name: mylab - storage_type: standard +- name: Create (or update) DevTest Lab + azure_rm_devtestlab: + resource_group: myResourceGroup + name: mylab + storage_type: standard ''' RETURN = ''' @@ -73,16 +78,13 @@ id: sample: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myResourceGroup/providers/microsoft.devtestlab/labs/mylab ''' -import time 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.polling import LROPoller from azure.core.exceptions import ResourceNotFoundError - from msrestazure.azure_operation import AzureOperationPoller from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass @@ -200,7 +202,7 @@ class AzureRMDevTestLab(AzureRMModuleBase): self.delete_devtestlab() # This currently doesnt' work as there is a bug in SDK / Service - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) else: self.log("DevTest Lab instance unchanged") @@ -225,7 +227,7 @@ class AzureRMDevTestLab(AzureRMModuleBase): response = self.mgmt_client.labs.begin_create_or_update(resource_group_name=self.resource_group, name=self.name, lab=self.lab) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlab_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlab_info.py index 63abdd357..6add55e59 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlab_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlab_info.py @@ -39,19 +39,19 @@ author: ''' EXAMPLES = ''' - - name: List instances of DevTest Lab by resource group - azure_rm_devtestlab_info: - resource_group: testrg - tags: - - key:value +- name: List instances of DevTest Lab by resource group + azure_rm_devtestlab_info: + resource_group: testrg + tags: + - key:value - - name: List instances of DevTest Lab in subscription - azure_rm_devtestlab_info: +- name: List instances of DevTest Lab in subscription + azure_rm_devtestlab_info: - - name: Get instance of DevTest Lab - azure_rm_devtestlab_info: - resource_group: testrg - name: testlab +- name: Get instance of DevTest Lab + azure_rm_devtestlab_info: + resource_group: testrg + name: testlab ''' RETURN = ''' @@ -137,7 +137,7 @@ labs: description: - The tags of the resource. returned: always - type: complex + type: dict sample: "{ 'MyTag': 'MyValue' }" ''' @@ -145,7 +145,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model from azure.core.exceptions import ResourceNotFoundError except ImportError: # This is handled in azure_rm_common diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabarmtemplate_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabarmtemplate_info.py index 42556856c..783a272dd 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabarmtemplate_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabarmtemplate_info.py @@ -46,12 +46,12 @@ author: ''' EXAMPLES = ''' - - name: Get information on DevTest Lab ARM Template - azure_rm_devtestlabarmtemplate_info: - resource_group: myResourceGroup - lab_name: myLab - artifact_source_name: public environment repo - name: WebApp +- name: Get information on DevTest Lab ARM Template + azure_rm_devtestlabarmtemplate_info: + resource_group: myResourceGroup + lab_name: myLab + artifact_source_name: public environment repo + name: WebApp ''' RETURN = ''' @@ -72,36 +72,43 @@ arm_templates: description: - Resource group name. returned: always + type: str sample: myResourceGroup lab_name: description: - DevTest Lab name. returned: always + type: str sample: myLab artifact_source_name: description: - Artifact source name. returned: always + type: str sample: public environment repo name: description: - ARM Template name. returned: always + type: str sample: WebApp display_name: description: - The tags of the resource. returned: always + type: str sample: Web App description: description: - The tags of the resource. returned: always + type: str sample: This template creates an Azure Web App without a data store. publisher: description: - The tags of the resource. returned: always + type: str sample: Microsoft ''' @@ -110,7 +117,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifact_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifact_info.py index 7100ad122..9ec729257 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifact_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifact_info.py @@ -46,12 +46,12 @@ author: ''' EXAMPLES = ''' - - name: Get instance of DevTest Lab Artifact - azure_rm_devtestlabartifact_info: - resource_group: myResourceGroup - lab_name: myLab - artifact_source_name: myArtifactSource - name: myArtifact +- name: Get instance of DevTest Lab Artifact + azure_rm_devtestlabartifact_info: + resource_group: myResourceGroup + lab_name: myLab + artifact_source_name: myArtifactSource + name: myArtifact ''' RETURN = ''' @@ -126,7 +126,7 @@ artifacts: description: - A dictionary containing parameters definition of the artifact. returned: always - type: complex + type: dict sample: {} ''' @@ -135,7 +135,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifactsource.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifactsource.py index 5ca4a5772..87f19bbd9 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifactsource.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifactsource.py @@ -20,51 +20,62 @@ options: resource_group: description: - The name of the resource group. + type: str required: True lab_name: description: - The name of the lab. + type: str required: True name: description: - The name of the artifact source. + type: str required: True display_name: description: - The artifact source's display name. + type: str uri: description: - The artifact source's URI. + type: str source_type: description: - The artifact source's type. + type: str choices: - 'vso' - 'github' folder_path: description: - The folder containing artifacts. + type: str arm_template_folder_path: description: - The folder containing Azure Resource Manager templates. + type: str branch_ref: description: - The artifact source's branch reference. + type: str security_token: description: - The security token to authenticate to the artifact source. + type: str is_enabled: description: - Indicates whether the artifact source is enabled. type: bool state: - description: - - Assert the state of the DevTest Labs Artifacts Source. - - Use C(present) to create or update an DevTest Labs Artifacts Source and C(absent) to delete it. - default: present - choices: - - absent - - present + description: + - Assert the state of the DevTest Labs Artifacts Source. + - Use C(present) to create or update an DevTest Labs Artifacts Source and C(absent) to delete it. + default: present + type: str + choices: + - absent + - present extends_documentation_fragment: - azure.azcollection.azure @@ -76,15 +87,15 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) DevTest Labs Artifacts Source - azure_rm_devtestlabartifactsource: - resource_group: myrg - lab_name: mylab - name: myartifacts - uri: https://github.com/myself/myrepo.git - source_type: github - folder_path: / - security_token: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +- name: Create (or update) DevTest Labs Artifacts Source + azure_rm_devtestlabartifactsource: + resource_group: myrg + lab_name: mylab + name: myartifacts + uri: https://github.com/myself/myrepo.git + source_type: github + folder_path: / + security_token: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ''' RETURN = ''' @@ -102,16 +113,12 @@ is_enabled: sample: true ''' -import time 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.polling import LROPoller from azure.core.exceptions import ResourceNotFoundError - from msrestazure.azure_operation import AzureOperationPoller from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass @@ -305,7 +312,7 @@ class AzureRMDevTestLabArtifactsSource(AzureRMModuleBase): lab_name=self.lab_name, name=self.name, artifact_source=self.artifact_source) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifactsource_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifactsource_info.py index 96bdde553..036a3da45 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifactsource_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifactsource_info.py @@ -46,11 +46,11 @@ author: ''' EXAMPLES = ''' - - name: Get instance of DevTest Lab Artifact Source - azure_rm_devtestlabartifactsource_info: - resource_group: myResourceGroup - lab_name: myLab - name: myArtifactSource +- name: Get instance of DevTest Lab Artifact Source + azure_rm_devtestlabartifactsource_info: + resource_group: myResourceGroup + lab_name: myLab + name: myArtifactSource ''' RETURN = ''' @@ -131,7 +131,7 @@ artifactsources: description: - The tags of the resource. returned: always - type: complex + type: dict sample: "{ 'MyTag': 'MyValue' }" ''' @@ -140,7 +140,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabcustomimage.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabcustomimage.py index 7b611706b..f24c6f7e5 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabcustomimage.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabcustomimage.py @@ -21,20 +21,25 @@ options: description: - The name of the resource group. required: True + type: str lab_name: description: - The name of the lab. required: True + type: str name: description: - The name of the custom image. required: True + type: str source_vm: description: - Source DevTest Lab virtual machine name. + type: str windows_os_state: description: - The state of the Windows OS. + type: str choices: - 'non_sysprepped' - 'sysprep_requested' @@ -42,6 +47,7 @@ options: linux_os_state: description: - The state of the Linux OS. + type: str choices: - 'non_deprovisioned' - 'deprovision_requested' @@ -49,17 +55,20 @@ options: description: description: - The description of the custom image. + type: str author: description: - The author of the custom image. + type: str state: - description: - - Assert the state of the Custom Image. - - Use C(present) to create or update an Custom Image and C(absent) to delete it. - default: present - choices: - - absent - - present + description: + - Assert the state of the Custom Image. + - Use C(present) to create or update an Custom Image and C(absent) to delete it. + default: present + type: str + choices: + - absent + - present extends_documentation_fragment: - azure.azcollection.azure @@ -89,16 +98,13 @@ id: sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myResourceGroup/providers/microsoft.devtestlab/labs/myLab/images/myImage" ''' -import time 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.polling import LROPoller from azure.core.exceptions import ResourceNotFoundError - from msrestazure.azure_operation import AzureOperationPoller from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass @@ -238,7 +244,7 @@ class AzureRMDtlCustomImage(AzureRMModuleBase): self.delete_customimage() # This currently doesnt' work as there is a bug in SDK / Service - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) else: self.log("Custom Image instance unchanged") @@ -264,7 +270,7 @@ class AzureRMDtlCustomImage(AzureRMModuleBase): lab_name=self.lab_name, name=self.name, custom_image=self.custom_image) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabcustomimage_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabcustomimage_info.py index 46ba637df..2c6d559aa 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabcustomimage_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabcustomimage_info.py @@ -46,17 +46,17 @@ author: ''' EXAMPLES = ''' - - name: Get instance of Custom Image - azure_rm_devtestlabcustomimage_info: - resource_group: myResourceGroup - lab_name: myLab - name: myImage - - - name: List instances of Custom Image in the lab - azure_rm_devtestlabcustomimage_info: - resource_group: myResourceGroup - lab_name: myLab - name: myImage +- name: Get instance of Custom Image + azure_rm_devtestlabcustomimage_info: + resource_group: myResourceGroup + lab_name: myLab + name: myImage + +- name: List instances of Custom Image in the lab + azure_rm_devtestlabcustomimage_info: + resource_group: myResourceGroup + lab_name: myLab + name: myImage ''' RETURN = ''' @@ -108,7 +108,7 @@ custom_images: description: - The tags of the resource. returned: always - type: complex + type: dict sample: "{ 'MyTag':'MyValue' }" ''' @@ -117,7 +117,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass @@ -137,7 +136,6 @@ class AzureRMDtlCustomImageInfo(AzureRMModuleBase): ), name=dict( type='str', - required=True ), tags=dict( type='list', diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabenvironment.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabenvironment.py index cd3735ce0..214ddbbe1 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabenvironment.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabenvironment.py @@ -49,6 +49,7 @@ options: description: - The parameters of the Azure Resource Manager template. type: list + elements: dict suboptions: name: description: @@ -101,16 +102,12 @@ id: ''' -import time 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.polling import LROPoller from azure.core.exceptions import ResourceNotFoundError - from msrestazure.azure_operation import AzureOperationPoller from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass @@ -149,6 +146,7 @@ class AzureRMDtlEnvironment(AzureRMModuleBase): ), deployment_parameters=dict( type='list', + elements='dict', options=dict( name=dict( type='str' @@ -248,7 +246,7 @@ class AzureRMDtlEnvironment(AzureRMModuleBase): self.delete_environment() # This currently doesn't work as there is a bug in SDK / Service - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) else: self.log("Environment instance unchanged") @@ -282,7 +280,7 @@ class AzureRMDtlEnvironment(AzureRMModuleBase): user_name=self.user_name, name=self.name, dtl_environment=self.dtl_environment) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabenvironment_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabenvironment_info.py index 675f6e848..4648ed1b7 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabenvironment_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabenvironment_info.py @@ -51,14 +51,14 @@ author: ''' EXAMPLES = ''' - - name: Get instance of Environment - azure_rm_devtestlabenvironment_info: - resource_group: myResourceGroup - lab_name: myLab - user_name: myUser - name: myEnvironment - tags: - - key:value +- name: Get instance of Environment + azure_rm_devtestlabenvironment_info: + resource_group: myResourceGroup + lab_name: myLab + user_name: myUser + name: myEnvironment + tags: + - key:value ''' RETURN = ''' @@ -116,7 +116,7 @@ environments: description: - The tags of the resource. returned: always - type: complex + type: dict sample: "{ 'MyTag': 'MyValue' }" ''' @@ -125,7 +125,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabpolicy.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabpolicy.py index f7aece825..2a3f2f953 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabpolicy.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabpolicy.py @@ -21,24 +21,30 @@ options: description: - The name of the resource group. required: True + type: str lab_name: description: - The name of the lab. required: True + type: str policy_set_name: description: - The name of the policy set. required: True + type: str name: description: - The name of the policy. required: True + type: str description: description: - The description of the policy. + type: str fact_name: description: - The fact name of the policy (e.g. C(lab_vm_count), C(lab_vm_size)), MaxVmsAllowedPerLab, etc. + type: str choices: - 'user_owned_lab_vm_count' - 'user_owned_lab_premium_vm_count' @@ -53,13 +59,14 @@ options: - The threshold of the policy (it could be either a maximum value or a list of allowed values). type: raw state: - description: - - Assert the state of the Policy. - - Use C(present) to create or update an Policy and C(absent) to delete it. - default: present - choices: - - absent - - present + description: + - Assert the state of the Policy. + - Use C(present) to create or update an Policy and C(absent) to delete it. + default: present + type: str + choices: + - absent + - present extends_documentation_fragment: - azure.azcollection.azure @@ -92,16 +99,13 @@ id: ''' -import time 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.polling import LROPoller from azure.core.exceptions import ResourceNotFoundError - from msrestazure.azure_operation import AzureOperationPoller from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass @@ -237,7 +241,7 @@ class AzureRMDtlPolicy(AzureRMModuleBase): self.delete_policy() # This currently doesnt' work as there is a bug in SDK / Service - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) else: self.log("Policy instance unchanged") @@ -265,7 +269,7 @@ class AzureRMDtlPolicy(AzureRMModuleBase): policy_set_name=self.policy_set_name, name=self.name, policy=self.policy) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabpolicy_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabpolicy_info.py index d6d452871..a8f3b104a 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabpolicy_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabpolicy_info.py @@ -51,14 +51,14 @@ author: ''' EXAMPLES = ''' - - name: Get instance of Policy - azure_rm_devtestlabpolicy_info: - resource_group: myResourceGroup - lab_name: myLab - policy_set_name: myPolicySet - name: myPolicy - tags: - - key:value +- name: Get instance of Policy + azure_rm_devtestlabpolicy_info: + resource_group: myResourceGroup + lab_name: myLab + policy_set_name: myPolicySet + name: myPolicy + tags: + - key:value ''' RETURN = ''' @@ -115,7 +115,7 @@ policies: description: - The tags of the resource. returned: always - type: complex + type: dict sample: "{ 'MyTag': 'MyValue' }" ''' @@ -124,7 +124,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabschedule.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabschedule.py index c672cb274..060b3baa0 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabschedule.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabschedule.py @@ -21,31 +21,37 @@ options: description: - The name of the resource group. required: True + type: str lab_name: description: - The name of the lab. required: True + type: str name: description: - The name of the schedule. required: True + type: str choices: - lab_vms_startup - lab_vms_shutdown time: description: - The time of day the schedule will occur. + type: str time_zone_id: description: - The time zone ID. + type: str state: - description: - - Assert the state of the Schedule. - - Use C(present) to create or update an Schedule and C(absent) to delete it. - default: present - choices: - - absent - - present + description: + - Assert the state of the Schedule. + - Use C(present) to create or update an Schedule and C(absent) to delete it. + default: present + type: str + choices: + - absent + - present extends_documentation_fragment: - azure.azcollection.azure @@ -57,13 +63,13 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) DevTest Lab Schedule - azure_rm_devtestlabschedule: - resource_group: myResourceGroup - lab_name: myLab - name: lab_vms_shutdown - time: "1030" - time_zone_id: "UTC+12" +- name: Create (or update) DevTest Lab Schedule + azure_rm_devtestlabschedule: + resource_group: myResourceGroup + lab_name: myLab + name: lab_vms_shutdown + time: "1030" + time_zone_id: "UTC+12" ''' RETURN = ''' @@ -76,16 +82,12 @@ id: abVmsShutdown" ''' -import time 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.polling import LROPoller from azure.core.exceptions import ResourceNotFoundError - from msrestazure.azure_operation import AzureOperationPoller from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass @@ -211,7 +213,7 @@ class AzureRMSchedule(AzureRMModuleBase): self.delete_schedule() # This currently doesn't work as there is a bug in SDK / Service - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) else: self.log("Schedule instance unchanged") @@ -237,7 +239,7 @@ class AzureRMSchedule(AzureRMModuleBase): lab_name=self.lab_name, name=self.name, schedule=self.schedule) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabschedule_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabschedule_info.py index dae349d2d..e366e0f99 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabschedule_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabschedule_info.py @@ -46,13 +46,13 @@ author: ''' EXAMPLES = ''' - - name: Get instance of Schedule - azure_rm_devtestlabschedule_info: - resource_group: myResourceGroup - lab_name: myLab - name: mySchedule - tags: - - key:value +- name: Get instance of Schedule + azure_rm_devtestlabschedule_info: + resource_group: myResourceGroup + lab_name: myLab + name: mySchedule + tags: + - key:value ''' RETURN = ''' @@ -103,7 +103,7 @@ schedules: description: - The tags of the resource. returned: always - type: complex + type: dict sample: "{ 'MyTag': 'MyValue' }" ''' @@ -113,7 +113,6 @@ from ansible.module_utils.common.dict_transformations import _camel_to_snake, _s try: from azure.core.exceptions import ResourceNotFoundError from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualmachine.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualmachine.py index f1edde75b..62e7db77a 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualmachine.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualmachine.py @@ -21,20 +21,25 @@ options: description: - The name of the resource group. required: True + type: str lab_name: description: - The name of the lab. required: True + type: str name: description: - The name of the virtual machine. required: True + type: str notes: description: - The notes of the virtual machine. + type: str os_type: description: - Base type of operating system. + type: str choices: - windows - linux @@ -44,84 +49,106 @@ options: - The list of choices varies depending on the subscription and location. Check your subscription for available choices. - Available values can be found on this website, link U(https://docs.microsoft.com/en-us/azure/virtual-machines/windows/sizes-general). - Required when I(state=present). + type: str user_name: description: - The user name of the virtual machine. + type: str password: description: - The password of the virtual machine administrator. + type: str ssh_key: description: - The SSH key of the virtual machine administrator. + type: str lab_subnet: description: - An existing subnet within lab's virtual network. - It can be the subnet's resource id. - It can be a dict which contains C(virtual_network_name) and C(name). + type: raw disallow_public_ip_address: description: - Indicates whether the virtual machine is to be created without a public IP address. + type: str artifacts: description: - The artifacts to be installed on the virtual machine. type: list + elements: dict suboptions: source_name: description: - The artifact's source name. + type: str source_path: description: - The artifact's path in the source repository. + type: str parameters: description: - The parameters of the artifact. type: list + elements: dict suboptions: name: description: - The name of the artifact parameter. + type: str value: description: - The value of the artifact parameter. + type: str image: description: - The Microsoft Azure Marketplace image reference of the virtual machine. + type: dict suboptions: offer: description: - The offer of the gallery image. + type: str publisher: description: - The publisher of the gallery image. + type: str sku: description: - The SKU of the gallery image. + type: str os_type: description: - The OS type of the gallery image. + type: str version: description: - The version of the gallery image. + type: str expiration_date: description: - The expiration date for VM. + type: str allow_claim: description: - Indicates whether another user can take ownership of the virtual machine. + type: str storage_type: description: - Storage type to use for virtual machine. + type: str choices: - standard - premium state: - description: - - Assert the state of the Virtual Machine. - - Use C(present) to create or update an Virtual Machine and C(absent) to delete it. - default: present - choices: - - absent - - present + description: + - Assert the state of the Virtual Machine. + - Use C(present) to create or update an Virtual Machine and C(absent) to delete it. + type: str + default: present + choices: + - absent + - present extends_documentation_fragment: - azure.azcollection.azure @@ -133,31 +160,31 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) Virtual Machine - azure_rm_devtestlabvirtualmachine: - resource_group: myrg - lab_name: mylab - name: myvm - notes: Virtual machine notes.... - os_type: linux - vm_size: Standard_A2_v2 - user_name: vmadmin - password: ZSuppas$$21! - lab_subnet: - name: myvnSubnet - virtual_network_name: myvn - disallow_public_ip_address: no - image: - offer: UbuntuServer - publisher: Canonical - sku: 16.04-LTS - os_type: Linux - version: latest - artifacts: - - source_name: myartifact - source_path: "/Artifacts/linux-install-mongodb" - allow_claim: no - expiration_date: "2019-02-22T01:49:12.117974Z" +- name: Create (or update) Virtual Machine + azure_rm_devtestlabvirtualmachine: + resource_group: myrg + lab_name: mylab + name: myvm + notes: Virtual machine notes.... + os_type: linux + vm_size: Standard_A2_v2 + user_name: vmadmin + password: ZSuppas$$21! + lab_subnet: + name: myvnSubnet + virtual_network_name: myvn + disallow_public_ip_address: false + image: + offer: 0001-com-ubuntu-server-focal + publisher: Canonical + sku: 20_04-lts + os_type: Linux + version: latest + artifacts: + - source_name: myartifact + source_path: "/Artifacts/linux-install-mongodb" + allow_claim: false + expiration_date: "2019-02-22T01:49:12.117974Z" ''' RETURN = ''' @@ -181,16 +208,13 @@ fqdn: sample: myvm.eastus.cloudapp.azure.com ''' -import time 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.polling import LROPoller from azure.core.exceptions import ResourceNotFoundError - from msrestazure.azure_operation import AzureOperationPoller from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass @@ -246,12 +270,17 @@ class AzureRMVirtualMachine(AzureRMModuleBase): ), artifacts=dict( type='list', + elements='dict', options=dict( - artifact_id=dict( + source_name=dict( + type='str', + ), + source_path=dict( type='str' ), parameters=dict( type='list', + elements='dict', options=dict( name=dict( type='str' @@ -463,7 +492,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase): lab_name=self.lab_name, name=self.name, lab_virtual_machine=self.lab_virtual_machine) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: @@ -486,7 +515,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase): self.log('Error attempting to delete the Virtual Machine instance.') self.fail("Error deleting the Virtual Machine instance: {0}".format(str(e))) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) return True diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualmachine_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualmachine_info.py index f33f2b976..24398136e 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualmachine_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualmachine_info.py @@ -46,13 +46,13 @@ author: ''' EXAMPLES = ''' - - name: Get instance of DTL Virtual Machine - azure_rm_devtestlabvirtualmachine_info: - resource_group: myResourceGroup - lab_name: myLab - name: myVm - tags: - - key:value +- name: Get instance of DTL Virtual Machine + azure_rm_devtestlabvirtualmachine_info: + resource_group: myResourceGroup + lab_name: myLab + name: myVm + tags: + - key:value ''' RETURN = ''' @@ -128,7 +128,7 @@ virtualmachines: - The SKU of the gallery image. returned: when created from gallery image type: str - sample: 16.04-LTS + sample: 20_04-lts publisher: description: - The publisher of the gallery image. @@ -199,7 +199,7 @@ virtualmachines: description: - The tags of the resource. returned: always - type: complex + type: dict sample: "{ 'foo': 'bar' }" ''' @@ -208,7 +208,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualnetwork.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualnetwork.py index 0ecd93098..a47a8c8f9 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualnetwork.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualnetwork.py @@ -21,28 +21,34 @@ options: description: - The name of the resource group. required: True + type: str lab_name: description: - The name of the lab. required: True + type: str name: description: - The name of the virtual network. required: True + type: str location: description: - The location of the resource. + type: str description: description: - The description of the virtual network. + type: str state: - description: - - Assert the state of the Virtual Network. - - Use C(present) to create or update an Virtual Network and C(absent) to delete it. - default: present - choices: - - absent - - present + description: + - Assert the state of the Virtual Network. + - Use C(present) to create or update an Virtual Network and C(absent) to delete it. + type: str + default: present + choices: + - absent + - present extends_documentation_fragment: - azure.azcollection.azure @@ -54,12 +60,12 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) Virtual Network - azure_rm_devtestlabvirtualnetwork: - resource_group: myResourceGroup - lab_name: mylab - name: myvn - description: My Lab Virtual Network +- name: Create (or update) Virtual Network + azure_rm_devtestlabvirtualnetwork: + resource_group: myResourceGroup + lab_name: mylab + name: myvn + description: My Lab Virtual Network ''' RETURN = ''' @@ -79,16 +85,12 @@ external_provider_resource_id: rtualNetworks/myvn" ''' -import time 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.polling import LROPoller from azure.core.exceptions import ResourceNotFoundError - from msrestazure.azure_operation import AzureOperationPoller from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass @@ -205,7 +207,7 @@ class AzureRMDevTestLabVirtualNetwork(AzureRMModuleBase): return self.results self.delete_virtualnetwork() # This currently doesn't work as there is a bug in SDK / Service - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) else: self.log("Virtual Network instance unchanged") @@ -232,7 +234,7 @@ class AzureRMDevTestLabVirtualNetwork(AzureRMModuleBase): lab_name=self.lab_name, name=self.name, virtual_network=self.virtual_network) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualnetwork_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualnetwork_info.py index b66b2f45b..23392468b 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualnetwork_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualnetwork_info.py @@ -41,17 +41,17 @@ author: ''' EXAMPLES = ''' - - name: Get instance of DevTest Lab Virtual Network - azure_rm_devtestlabvirtualnetwork_info: - resource_group: myResourceGroup - lab_name: myLab - name: myVirtualNetwork - - - name: List all Virtual Networks in DevTest Lab - azure_rm_devtestlabvirtualnetwork_info: - resource_group: myResourceGroup - lab_name: myLab - name: myVirtualNetwork +- name: Get instance of DevTest Lab Virtual Network + azure_rm_devtestlabvirtualnetwork_info: + resource_group: myResourceGroup + lab_name: myLab + name: myVirtualNetwork + +- name: List all Virtual Networks in DevTest Lab + azure_rm_devtestlabvirtualnetwork_info: + resource_group: myResourceGroup + lab_name: myLab + name: myVirtualNetwork ''' RETURN = ''' @@ -112,7 +112,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError from azure.mgmt.devtestlabs import DevTestLabsClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_diskencryptionset.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_diskencryptionset.py index 93bd8ab47..f76f784eb 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_diskencryptionset.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_diskencryptionset.py @@ -153,7 +153,7 @@ state: ''' from ansible.module_utils.basic import _load_params -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, HAS_AZURE, \ +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, \ format_resource_id, normalize_location_name try: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_dnsrecordset.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_dnsrecordset.py index 55b682be6..32448964a 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_dnsrecordset.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_dnsrecordset.py @@ -151,9 +151,9 @@ EXAMPLES = ''' record_type: "{{ item.type }}" records: "{{ item.records }}" with_items: - - { name: 'servera', type: 'A', records: [ { entry: '10.10.10.20' }, { entry: '10.10.10.21' }] } - - { name: 'serverb', type: 'A', records: [ { entry: '10.10.10.30' }, { entry: '10.10.10.41' }] } - - { name: 'serverc', type: 'A', records: [ { entry: '10.10.10.40' }, { entry: '10.10.10.41' }] } + - {name: 'servera', type: 'A', records: [{entry: '10.10.10.20'}, {entry: '10.10.10.21'}]} + - {name: 'serverb', type: 'A', records: [{entry: '10.10.10.30'}, {entry: '10.10.10.41'}]} + - {name: 'serverc', type: 'A', records: [{entry: '10.10.10.40'}, {entry: '10.10.10.41'}]} - name: create SRV records in a new record set azure_rm_dnsrecordset: @@ -163,11 +163,11 @@ EXAMPLES = ''' time_to_live: 7200 record_type: SRV records: - - entry: sip.testing.com - preference: 10 - priority: 20 - weight: 10 - port: 5060 + - entry: sip.testing.com + preference: 10 + priority: 20 + weight: 10 + port: 5060 - name: create PTR record in a new record set azure_rm_dnsrecordset: @@ -176,7 +176,7 @@ EXAMPLES = ''' zone_name: testing.com record_type: PTR records: - - entry: servera.testing.com + - entry: servera.testing.com - name: create TXT record in a new record set azure_rm_dnsrecordset: @@ -185,7 +185,7 @@ EXAMPLES = ''' zone_name: testing.com record_type: TXT records: - - entry: 'v=spf1 a -all' + - entry: 'v=spf1 a -all' - name: Update SOA record azure_rm_dnsrecordset: @@ -201,7 +201,6 @@ EXAMPLES = ''' retry_time: 399 expire_time: 2419299 minimum_ttl: 399 - ''' RETURN = ''' @@ -277,12 +276,9 @@ state: ] ''' -import inspect -import sys import copy from ansible.module_utils.basic import _load_params -from ansible.module_utils.six import iteritems from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, HAS_AZURE try: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_dnszone.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_dnszone.py index f5033be38..3d95d33a7 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_dnszone.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_dnszone.py @@ -37,20 +37,24 @@ options: description: - name of resource group. required: true + type: str name: description: - Name of the DNS zone. required: true + type: str state: description: - Assert the state of the zone. Use C(present) to create or update and C(absent) to delete. default: present + type: str choices: - absent - present type: description: - The type of this DNS zone (C(public) or C(private)). + type: str choices: - public - private @@ -89,7 +93,6 @@ EXAMPLES = ''' resource_group: myResourceGroup name: example.com state: absent - ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_dnszone_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_dnszone_info.py index 8a37a131d..75a228e6b 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_dnszone_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_dnszone_info.py @@ -23,9 +23,11 @@ options: resource_group: description: - Limit results by resource group. Required when filtering by name. + type: str name: description: - Only show results for a specific zone. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -81,14 +83,17 @@ dnszones: description: - id of the DNS Zone. sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/dnszones/azure.com" + type: str name: description: - name of the DNS zone. sample: azure.com + type: str type: description: - The type of this DNS zone (C(public) or C(private)). sample: private + type: str registration_virtual_networks: description: - A list of references to virtual networks that register hostnames in this DNS zone. diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_eventhub.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_eventhub.py index ecc8bc424..5da748a17 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_eventhub.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_eventhub.py @@ -99,7 +99,7 @@ EXAMPLES = ''' namespace_name: myNamespace name: myhub tags: - - a: b + - a: b sku: free - name: Delete Event Hub @@ -122,7 +122,6 @@ EXAMPLES = ''' resource_group: testgroupans namespace_name: myNamespace state: absent - ''' RETURN = ''' @@ -157,7 +156,6 @@ state: ''' try: - from azure.core.exceptions import ResourceNotFoundError from azure.mgmt.eventhub.models import Eventhub, EHNamespace from azure.mgmt.eventhub.models import Sku except ImportError: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_eventhub_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_eventhub_info.py index 9e0084ca6..c62ef3a7b 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_eventhub_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_eventhub_info.py @@ -38,10 +38,10 @@ author: EXAMPLES = ''' - - name: Get facts of specific Event hub - community.azure.azure_rm_eventhub_info: - resource_group: myResourceGroup - name: myEventHub +- name: Get facts of specific Event hub + community.azure.azure_rm_eventhub_info: + resource_group: myResourceGroup + name: myEventHub ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_expressroute.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_expressroute.py index 93b53dc70..fa585f90d 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_expressroute.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_expressroute.py @@ -113,9 +113,9 @@ EXAMPLES = ''' allow_classic_operations: true global_reach_enabled: false tags: - - a: b + - a: b authorizations: - - name: authorization_test + - name: authorization_test service_provider_properties: service_provider_name: Aryaka Networks peering_location: Seattle @@ -129,7 +129,6 @@ EXAMPLES = ''' resource_group: rg name: exp state: absent - ''' RETURN = ''' @@ -179,7 +178,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError - from azure.mgmt.network import NetworkManagementClient except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_expressroute_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_expressroute_info.py index fead26069..b23ef3dde 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_expressroute_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_expressroute_info.py @@ -42,13 +42,12 @@ author: EXAMPLES = ''' - - name: Get facts of specific expressroute - community.azure.azure_rm_expressroute_info: - resource_group: myResourceGroup - name: myExpressRoute - tags: - - key:value - +- name: Get facts of specific expressroute + community.azure.azure_rm_expressroute_info: + resource_group: myResourceGroup + name: myExpressRoute + tags: + - key:value ''' RETURN = ''' @@ -98,8 +97,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError - from azure.mgmt.network import NetworkManagementClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_firewallpolicy.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_firewallpolicy.py index e7dfdafe2..dab7f5403 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_firewallpolicy.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_firewallpolicy.py @@ -246,7 +246,7 @@ state: ''' from ansible.module_utils.basic import _load_params -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, HAS_AZURE, \ +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, \ format_resource_id, normalize_location_name import copy diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_firewallpolicy_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_firewallpolicy_info.py index 2c5c6c5dc..4dc7c7053 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_firewallpolicy_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_firewallpolicy_info.py @@ -104,7 +104,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError - from azure.common import AzureMissingResourceHttpError, AzureHttpError except Exception: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_functionapp.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_functionapp.py index cf0bc00b0..a76a94ef9 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_functionapp.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_functionapp.py @@ -22,13 +22,16 @@ options: required: true aliases: - resource_group_name + type: str name: description: - Name of the Azure Function App. required: true + type: str location: description: - Valid Azure location. Defaults to location of the resource group. + type: str plan: description: - App service plan. @@ -38,35 +41,46 @@ options: - It can be a dict which contains C(name), C(resource_group). - C(name). Name of app service plan. - C(resource_group). Resource group name of app service plan. + type: raw container_settings: - description: Web app container settings. + description: + - Web app container settings. + type: dict suboptions: name: description: - Name of container. For example "imagename:tag". + required: True + type: str registry_server_url: description: - Container registry server url. For example C(mydockerregistry.io). + type: str registry_server_user: description: - The container registry server user name. + type: str registry_server_password: description: - The container registry server password. + type: str storage_account: description: - Name of the storage account to use. - required: true + - Required when creating. + type: str aliases: - storage - storage_account_name app_settings: description: - Dictionary containing application settings. + type: dict state: description: - Assert the state of the Function App. Use C(present) to create or update a Function App and C(absent) to delete. default: present + type: str choices: - absent - present diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_functionapp_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_functionapp_info.py index 3b4904e35..4a33fb684 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_functionapp_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_functionapp_info.py @@ -19,11 +19,13 @@ options: name: description: - Only show results for a specific Function App. + type: str resource_group: description: - Limit results to a resource group. Required when filtering by name. aliases: - resource_group_name + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -38,19 +40,19 @@ author: ''' EXAMPLES = ''' - - name: Get facts for one Function App - azure_rm_functionapp_info: - resource_group: myResourceGroup - name: myfunctionapp +- name: Get facts for one Function App + azure_rm_functionapp_info: + resource_group: myResourceGroup + name: myfunctionapp - - name: Get facts for all Function Apps in a resource group - azure_rm_functionapp_info: - resource_group: myResourceGroup +- name: Get facts for all Function Apps in a resource group + azure_rm_functionapp_info: + resource_group: myResourceGroup - - name: Get facts for all Function Apps by tags - azure_rm_functionapp_info: - tags: - - testing +- name: Get facts for all Function Apps by tags + azure_rm_functionapp_info: + tags: + - testing ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_gallery.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_gallery.py index 3b5e14408..cb902ace7 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_gallery.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_gallery.py @@ -72,15 +72,8 @@ id: import time import json -import re 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 copy import deepcopy -try: - from msrestazure.azure_exceptions import CloudError -except ImportError: - # This is handled in azure_rm_common - pass class Actions: @@ -152,6 +145,7 @@ class AzureRMGalleries(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) resource_group = self.get_resource_group(self.resource_group) @@ -243,14 +237,14 @@ class AzureRMGalleries(AzureRMModuleBaseExt): self.status_code, 600, 30) - except CloudError as exc: + except Exception as exc: self.log('Error attempting to create the Gallery instance.') self.fail('Error creating the Gallery instance: {0}'.format(str(exc))) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: - response = {'text': response.text} + response = {'text': response.context['deserialized_data']} return response @@ -265,7 +259,7 @@ class AzureRMGalleries(AzureRMModuleBaseExt): self.status_code, 600, 30) - except CloudError as e: + except Exception as e: self.log('Error attempting to delete the Gallery instance.') self.fail('Error deleting the Gallery instance: {0}'.format(str(e))) @@ -283,11 +277,11 @@ class AzureRMGalleries(AzureRMModuleBaseExt): self.status_code, 600, 30) - response = json.loads(response.text) + response = json.loads(response.body()) found = True self.log("Response : {0}".format(response)) # self.log("AzureFirewall instance : {0} found".format(response.name)) - except CloudError as e: + except Exception as e: self.log('Did not find the AzureFirewall instance.') if found is True: return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_gallery_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_gallery_info.py index 58cb29dd5..cd02bec28 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_gallery_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_gallery_info.py @@ -41,7 +41,6 @@ EXAMPLES = ''' azure_rm_gallery_info: resource_group: myResourceGroup name: myGallery - ''' RETURN = ''' @@ -90,16 +89,9 @@ galleries: ''' -import time import json from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_rest import GenericRestClient -from copy import deepcopy -try: - from msrestazure.azure_exceptions import CloudError -except Exception: - # handled in azure_rm_common - pass class AzureRMGalleriesInfo(AzureRMModuleBase): @@ -136,6 +128,7 @@ class AzureRMGalleriesInfo(AzureRMModuleBase): setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if (self.resource_group is not None and self.name is not None): @@ -174,9 +167,9 @@ class AzureRMGalleriesInfo(AzureRMModuleBase): self.status_code, 600, 30) - results = json.loads(response.text) + results = json.loads(response.body()) # self.log('Response : {0}'.format(response)) - except CloudError as e: + except Exception as e: self.log('Could not get info for @(Model.ModuleOperationNameUpper).') return self.format_item(results) @@ -204,9 +197,9 @@ class AzureRMGalleriesInfo(AzureRMModuleBase): self.status_code, 600, 30) - results = json.loads(response.text) + results = json.loads(response.body()) # self.log('Response : {0}'.format(response)) - except CloudError as e: + except Exception as e: self.log('Could not get info for @(Model.ModuleOperationNameUpper).') return [self.format_item(x) for x in results['value']] if results['value'] else [] @@ -231,9 +224,9 @@ class AzureRMGalleriesInfo(AzureRMModuleBase): self.status_code, 600, 30) - results = json.loads(response.text) + results = json.loads(response.body()) # self.log('Response : {0}'.format(response)) - except CloudError as e: + except Exception as e: self.log('Could not get info for @(Model.ModuleOperationNameUpper).') return [self.format_item(x) for x in results['value']] if results['value'] else [] diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimage.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimage.py index a0335fa01..c14aedd4a 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimage.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimage.py @@ -56,18 +56,18 @@ options: os_type: description: - This property allows you to specify the type of the OS that is included in the disk when creating a VM from a managed image. + - Required when creating. choices: - windows - linux - required: true type: str os_state: description: - The allowed values for OS State are C(generalized). + - Required when creating. choices: - generalized - specialized - required: true type: str hypervgeneration: description: @@ -86,7 +86,7 @@ options: identifier: description: - Image identifier. - required: true + - Required when creating. type: dict suboptions: publisher: @@ -144,6 +144,7 @@ options: description: - A list of disallowed disk types. type: list + elements: str purchase_plan: description: - Purchase plan. @@ -205,15 +206,8 @@ id: import time import json -import re 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 copy import deepcopy -try: - from msrestazure.azure_exceptions import CloudError -except ImportError: - # This is handled in azure_rm_common - pass class Actions: @@ -338,6 +332,7 @@ class AzureRMGalleryImages(AzureRMModuleBaseExt): options=dict( disk_types=dict( type='list', + elements='str', disposition='diskTypes' ) ) @@ -399,6 +394,7 @@ class AzureRMGalleryImages(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) resource_group = self.get_resource_group(self.resource_group) @@ -492,14 +488,14 @@ class AzureRMGalleryImages(AzureRMModuleBaseExt): self.status_code, 600, 30) - except CloudError as exc: + except Exception as exc: self.log('Error attempting to create the GalleryImage instance.') self.fail('Error creating the GalleryImage instance: {0}'.format(str(exc))) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: - response = {'text': response.text} + response = {'text': response.context['deserialized_data']} return response @@ -514,7 +510,7 @@ class AzureRMGalleryImages(AzureRMModuleBaseExt): self.status_code, 600, 30) - except CloudError as e: + except Exception as e: self.log('Error attempting to delete the GalleryImage instance.') self.fail('Error deleting the GalleryImage instance: {0}'.format(str(e))) @@ -532,11 +528,11 @@ class AzureRMGalleryImages(AzureRMModuleBaseExt): self.status_code, 600, 30) - response = json.loads(response.text) + response = json.loads(response.body()) found = True self.log("Response : {0}".format(response)) # self.log("AzureFirewall instance : {0} found".format(response.name)) - except CloudError as e: + except Exception as e: self.log('Did not find the AzureFirewall instance.') if found is True: return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimage_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimage_info.py index 90bcbe244..0f1c5020f 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimage_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimage_info.py @@ -47,7 +47,6 @@ EXAMPLES = ''' resource_group: myResourceGroup gallery_name: myGallery name: myImage - ''' RETURN = ''' @@ -85,12 +84,12 @@ images: os_state: description: - The allowed values for OS State are C(generalized). - type: OperatingSystemStateTypes + type: str sample: "Generalized" os_type: description: - This property allows you to specify the type of the OS that is included in the disk when creating a VM from a managed image. - type: OperatingSystemTypes + type: str sample: "linux/windows" identifier: description: @@ -115,16 +114,9 @@ images: ''' -import time import json from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_rest import GenericRestClient -from copy import deepcopy -try: - from msrestazure.azure_exceptions import CloudError -except Exception: - # handled in azure_rm_common - pass class AzureRMGalleryImagesInfo(AzureRMModuleBase): @@ -167,6 +159,7 @@ class AzureRMGalleryImagesInfo(AzureRMModuleBase): setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if (self.resource_group is not None and @@ -208,9 +201,9 @@ class AzureRMGalleryImagesInfo(AzureRMModuleBase): self.status_code, 600, 30) - results = json.loads(response.text) + results = json.loads(response.body()) # self.log('Response : {0}'.format(response)) - except CloudError as e: + except Exception as e: self.log('Could not get info for @(Model.ModuleOperationNameUpper).') return self.format_item(results) @@ -241,9 +234,9 @@ class AzureRMGalleryImagesInfo(AzureRMModuleBase): self.status_code, 600, 30) - results = json.loads(response.text) + results = json.loads(response.body()) # self.log('Response : {0}'.format(response)) - except CloudError as e: + except Exception as e: self.log('Could not get info for @(Model.ModuleOperationNameUpper).') return [self.format_item(x) for x in results['value']] if results['value'] else [] diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimageversion.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimageversion.py index c539e3d4a..9d61bf874 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimageversion.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimageversion.py @@ -45,7 +45,7 @@ options: storage_profile: description: - Storage profile - required: true + - Required when creating. type: dict suboptions: source_image: @@ -59,12 +59,12 @@ options: description: - os disk snapshot - Mutual exclusive with source_image - type: raw + type: dict suboptions: source: description: - Reference to os disk snapshot. Could be resource ID or dictionary containing I(resource_group) and I(name) - type: str + type: raw host_caching: description: - host disk caching @@ -79,11 +79,12 @@ options: - list of data disk snapshot - Mutual exclusive with source_image type: list + elements: raw suboptions: source: description: - Reference to data disk snapshot. Could be resource ID or dictionary containing I(resource_group) and I(name) - type: str + type: raw lun: description: - lun of the data disk @@ -100,7 +101,6 @@ options: publishing_profile: description: - Publishing profile. - required: true type: dict suboptions: target_regions: @@ -108,17 +108,19 @@ options: - The target regions where the Image Version is going to be replicated to. - This property is updatable. type: list + elements: raw suboptions: name: description: - Region name. type: str + required: true regional_replica_count: description: - The number of replicas of the Image Version to be created per region. - This property would take effect for a region when regionalReplicaCount is not specified. - This property is updatable. - type: str + type: int storage_account_type: description: - Storage account type. @@ -127,10 +129,12 @@ options: description: - Managed image reference, could be resource ID, or dictionary containing I(resource_group) and I(name) - Obsolete since 2.10, use storage_profile instead + type: raw snapshot: description: - Source snapshot to be used. - Obsolete since 2.10, use storage_profile instead + type: raw replica_count: description: - The number of replicas of the Image Version to be created per region. @@ -152,6 +156,9 @@ options: - Specifies the storage account type to be used to store the image. - This property is not updatable. type: str + choices: + - Standard_LRS + - Standard_ZRS state: description: - Assert the state of the GalleryImageVersion. @@ -179,7 +186,7 @@ EXAMPLES = ''' location: East US publishing_profile: end_of_life_date: "2020-10-01t00:00:00+00:00" - exclude_from_latest: yes + exclude_from_latest: true replica_count: 4 storage_account_type: Standard_LRS target_regions: @@ -189,7 +196,7 @@ EXAMPLES = ''' regional_replica_count: 3 storage_account_type: Standard_LRS storage_profile: - source_image: /subscriptions/sub123/resourceGroups/group123/providers/Microsoft.Compute/images/myOsImage + source_image: /subscriptions/sub123/resourceGroups/group123/providers/Microsoft.Compute/images/myOsImage - name: Create a gallery image version from another gallery image version azure_rm_galleryimageversion: @@ -200,7 +207,7 @@ EXAMPLES = ''' location: East US publishing_profile: end_of_life_date: "2020-10-01t00:00:00+00:00" - exclude_from_latest: yes + exclude_from_latest: true replica_count: 4 storage_account_type: Standard_LRS target_regions: @@ -210,10 +217,10 @@ EXAMPLES = ''' regional_replica_count: 3 storage_account_type: Standard_LRS storage_profile: - source_image: - version: 1.1.0 - gallery_name: myGallery2 - gallery_image_name: myGalleryImage2 + source_image: + version: 1.1.0 + gallery_name: myGallery2 + gallery_image_name: myGalleryImage2 - name: Create gallery image by using one os dist snapshot and zero or many data disk snapshots azure_rm_galleryimageversion: @@ -224,7 +231,7 @@ EXAMPLES = ''' location: East US publishing_profile: end_of_life_date: "2020-10-01t00:00:00+00:00" - exclude_from_latest: yes + exclude_from_latest: true replica_count: 1 storage_account_type: Standard_LRS target_regions: @@ -233,13 +240,13 @@ EXAMPLES = ''' storage_account_type: Standard_LRS storage_profile: os_disk: - source: "/subscriptions/mySub/resourceGroups/myGroup/providers/Microsoft.Compute/snapshots/os_snapshot_vma" + source: "/subscriptions/mySub/resourceGroups/myGroup/providers/Microsoft.Compute/snapshots/os_snapshot_vma" data_disks: - - lun: 0 - source: - name: data_snapshot_vma - - lun: 1 - source: "/subscriptions/mySub/resourceGroups/myGroup/providers/Microsoft.Compute/snapshots/data_snapshot_vmb" + - lun: 0 + source: + name: data_snapshot_vma + - lun: 1 + source: "/subscriptions/mySub/resourceGroups/myGroup/providers/Microsoft.Compute/snapshots/data_snapshot_vmb" ''' RETURN = ''' @@ -256,11 +263,6 @@ import time 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 -try: - from msrestazure.azure_exceptions import CloudError -except ImportError: - # This is handled in azure_rm_common - pass class Actions: @@ -347,6 +349,7 @@ class AzureRMGalleryImageVersions(AzureRMModuleBaseExt): ), data_disks=dict( type='list', + elements='raw', disposition='dataDiskImages', purgeIfNone=True, options=dict( @@ -376,6 +379,7 @@ class AzureRMGalleryImageVersions(AzureRMModuleBaseExt): options=dict( target_regions=dict( type='list', + elements='raw', disposition='targetRegions', options=dict( name=dict( @@ -481,6 +485,7 @@ class AzureRMGalleryImageVersions(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) resource_group = self.get_resource_group(self.resource_group) @@ -574,14 +579,14 @@ class AzureRMGalleryImageVersions(AzureRMModuleBaseExt): self.status_code, 600, 30) - except CloudError as exc: + except Exception as exc: self.log('Error attempting to create the GalleryImageVersion instance.') self.fail('Error creating the GalleryImageVersion instance: {0}'.format(str(exc))) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: - response = {'text': response.text} + response = {'text': response.context['deserialized_data']} while response['properties']['provisioningState'] == 'Creating': time.sleep(60) @@ -600,7 +605,7 @@ class AzureRMGalleryImageVersions(AzureRMModuleBaseExt): self.status_code, 600, 30) - except CloudError as e: + except Exception as e: self.log('Error attempting to delete the GalleryImageVersion instance.') self.fail('Error deleting the GalleryImageVersion instance: {0}'.format(str(e))) return True @@ -617,11 +622,11 @@ class AzureRMGalleryImageVersions(AzureRMModuleBaseExt): self.status_code, 600, 30) - response = json.loads(response.text) + response = json.loads(response.body()) found = True self.log("Response : {0}".format(response)) # self.log("AzureFirewall instance : {0} found".format(response.name)) - except CloudError as e: + except Exception as e: self.log('Did not find the AzureFirewall instance.') if found is True: return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimageversion_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimageversion_info.py index 1d448ca12..b4c7e89a2 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimageversion_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimageversion_info.py @@ -54,7 +54,6 @@ EXAMPLES = ''' gallery_name: myGallery gallery_image_name: myImage name: myVersion - ''' RETURN = ''' @@ -101,16 +100,9 @@ versions: ''' -import time import json from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_rest import GenericRestClient -from copy import deepcopy -try: - from msrestazure.azure_exceptions import CloudError -except Exception: - # handled in azure_rm_common - pass class AzureRMGalleryImageVersionsInfo(AzureRMModuleBase): @@ -158,6 +150,7 @@ class AzureRMGalleryImageVersionsInfo(AzureRMModuleBase): setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if (self.resource_group is not None and @@ -202,9 +195,9 @@ class AzureRMGalleryImageVersionsInfo(AzureRMModuleBase): self.status_code, 600, 30) - results = json.loads(response.text) + results = json.loads(response.body()) # self.log('Response : {0}'.format(response)) - except CloudError as e: + except Exception as e: self.log('Could not get info for @(Model.ModuleOperationNameUpper).') return self.format_item(results) @@ -247,7 +240,7 @@ class AzureRMGalleryImageVersionsInfo(AzureRMModuleBase): 0, 0) try: - response = json.loads(response.text) + response = json.loads(response.body()) if isinstance(response, dict): if response.get('value'): results['response'] = results['response'] + response['value'] @@ -259,7 +252,7 @@ class AzureRMGalleryImageVersionsInfo(AzureRMModuleBase): if not skiptoken: break # self.log('Response : {0}'.format(response)) - except CloudError as e: + except Exception as e: self.log('Could not get info for @(Model.ModuleOperationNameUpper).') return [self.format_item(x) for x in results['response']] if results['response'] else [] diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hdinsightcluster.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hdinsightcluster.py index ce498df22..2ce7e16f3 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hdinsightcluster.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hdinsightcluster.py @@ -21,34 +21,42 @@ options: description: - The name of the resource group. required: True + type: str name: description: - The name of the cluster. required: True + type: str location: description: - Resource location. If not set, location from the resource group will be used as default. + type: str cluster_version: description: - The version of the cluster. For example C(3.6). + type: str os_type: description: - The type of operating system. + type: str choices: - 'linux' tier: description: - The cluster tier. + type: str choices: - 'standard' - 'premium' cluster_definition: description: - The cluster definition. + type: dict suboptions: kind: description: - The type of cluster. + type: str choices: - hadoop - spark @@ -57,17 +65,21 @@ options: gateway_rest_username: description: - Gateway REST user name. + type: str gateway_rest_password: description: - Gateway REST password. + type: str compute_profile_roles: description: - The list of roles in the cluster. type: list + elements: dict suboptions: name: description: - The name of the role. + type: str choices: - 'headnode' - 'workernode' @@ -75,47 +87,59 @@ options: min_instance_count: description: - The minimum instance count of the cluster. + type: int target_instance_count: description: - The instance count of the cluster. + type: int vm_size: description: - The size of the VM. + type: str linux_profile: description: - The Linux OS profile. + type: dict suboptions: username: description: - SSH user name. + type: str password: description: - SSH password. + type: str storage_accounts: description: - The list of storage accounts in the cluster. type: list + elements: dict suboptions: name: description: - Blob storage endpoint. For example storage_account_name.blob.core.windows.net. + type: str is_default: description: - Whether or not the storage account is the default storage account. + type: bool container: description: - The container in the storage account. + type: str key: description: - The storage account access key. + type: str state: - description: - - Assert the state of the cluster. - - Use C(present) to create or update a cluster and C(absent) to delete it. - default: present - choices: - - absent - - present + description: + - Assert the state of the cluster. + - Use C(present) to create or update a cluster and C(absent) to delete it. + default: present + type: str + choices: + - absent + - present extends_documentation_fragment: - azure.azcollection.azure @@ -141,14 +165,13 @@ EXAMPLES = ''' gateway_rest_password: MuABCPassword!!@123 storage_accounts: - name: myStorageAccount.blob.core.windows.net - is_default: yes + is_default: true container: myContainer key: GExmaxH4lDNdHA9nwAsCt8t4AOQas2y9vXQP1kKALTram7Q3/5xLVIab3+nYG1x63Xyak9/VXxQyNBHA9pDWw== compute_profile_roles: - name: headnode target_instance_count: 2 - hardware_profile: - vm_size: Standard_D3 + vm_size: Standard_D3 linux_profile: username: sshuser password: MuABCPassword!!@123 @@ -169,15 +192,12 @@ id: sample: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.HDInsight/clusters/myCluster ''' -import time from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: from azure.core.polling import LROPoller from azure.core.exceptions import ResourceNotFoundError - from msrestazure.azure_operation import AzureOperationPoller from azure.mgmt.hdinsight import HDInsightManagementClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass @@ -219,10 +239,31 @@ class AzureRMClusters(AzureRMModuleBase): type='dict' ), compute_profile_roles=dict( - type='list' + type='list', + elements='dict', + options=dict( + name=dict(type='str', choices=['headnode', 'workernode', 'zookepernode']), + min_instance_count=dict(type='int'), + target_instance_count=dict(type='int'), + vm_size=dict(type='str'), + linux_profile=dict( + type='dict', + options=dict( + username=dict(type='str'), + password=dict(type='str', no_log=True) + ) + ), + ) ), storage_accounts=dict( - type='list' + type='list', + elements='dict', + options=dict( + name=dict(type='str'), + is_default=dict(type='bool'), + container=dict(type='str'), + key=dict(type='str', no_log=True) + ) ), state=dict( type='str', @@ -360,21 +401,21 @@ class AzureRMClusters(AzureRMModuleBase): response = self.mgmt_client.clusters.begin_create(resource_group_name=self.resource_group, cluster_name=self.name, parameters=self.parameters) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) else: if self.tags_changed: response = self.mgmt_client.clusters.update(resource_group_name=self.resource_group, cluster_name=self.name, parameters={'tags': self.parameters.get('tags')}) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) if self.new_instance_count: response = self.mgmt_client.clusters.begin_resize(resource_group_name=self.resource_group, cluster_name=self.name, role_name='workernode', parameters={'target_instance_count': self.new_instance_count}) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: self.fail("Error creating or updating Cluster instance: {0}".format(str(exc))) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hdinsightcluster_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hdinsightcluster_info.py index 09dce3ee3..afb3211ea 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hdinsightcluster_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hdinsightcluster_info.py @@ -20,9 +20,11 @@ options: resource_group: description: - Name of an Azure resource group. + type: str name: description: - HDInsight cluster name. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -38,16 +40,16 @@ author: ''' EXAMPLES = ''' - - name: Get instance of HDInsight Cluster - azure_rm_hdinsightcluster_info: - resource_group: myResourceGroup - name: myCluster - - - name: List instances of HDInsight Cluster - azure_rm_hdinsightcluster_info: - resource_group: myResourceGroup - tags: - - key:value +- name: Get instance of HDInsight Cluster + azure_rm_hdinsightcluster_info: + resource_group: myResourceGroup + name: myCluster + +- name: List instances of HDInsight Cluster + azure_rm_hdinsightcluster_info: + resource_group: myResourceGroup + tags: + - key:value ''' RETURN = ''' @@ -102,6 +104,7 @@ clusters: cluster_definition: description: - The cluster definition. + type: complex contains: kind: description: @@ -112,7 +115,7 @@ clusters: compute_profile_roles: description: - The list of roles in the cluster. - type: list + type: complex contains: name: description: @@ -135,6 +138,7 @@ clusters: linux_profile: description: - The Linux OS profile. + type: dict contains: username: description: @@ -145,7 +149,7 @@ clusters: connectivity_endpoints: description: - Cluster's connectivity endpoints. - type: list + type: complex contains: location: description: @@ -175,17 +179,15 @@ clusters: description: - The tags of the resource. returned: always - type: complex + type: dict sample: {} ''' from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase -from ansible.module_utils.common.dict_transformations import _camel_to_snake try: from azure.core.exceptions import ResourceNotFoundError from azure.mgmt.hdinsight import HDInsightManagementClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hostgroup.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hostgroup.py index d7e80bf14..235728b64 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hostgroup.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hostgroup.py @@ -143,7 +143,7 @@ state: ''' from ansible.module_utils.basic import _load_params -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, HAS_AZURE, \ +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, \ normalize_location_name try: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_image.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_image.py index 8c4fb4475..5efd76074 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_image.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_image.py @@ -39,6 +39,7 @@ options: - List of data disk sources, including unmanaged blob URI, managed disk id or name, or snapshot id or name. type: list elements: str + default: [] location: description: - Location of the image. Derived from I(resource_group) if not specified. @@ -87,8 +88,8 @@ EXAMPLES = ''' name: myImage source: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroup/myResourceGroup/providers/Microsoft.Compute/disks/disk001 data_disk_sources: - - datadisk001 - - datadisk002 + - datadisk001 + - datadisk002 os_type: Linux - name: Create an image from os disk via dict @@ -96,12 +97,12 @@ EXAMPLES = ''' resource_group: myResourceGroup name: myImage source: - type: disks - resource_group: myResourceGroup - name: disk001 + type: disks + resource_group: myResourceGroup + name: disk001 data_disk_sources: - - datadisk001 - - datadisk002 + - datadisk001 + - datadisk002 os_type: Linux - name: Delete an image @@ -124,7 +125,7 @@ id: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, format_resource_id try: - from msrestazure.tools import parse_resource_id + from azure.mgmt.core.tools import parse_resource_id from azure.core.exceptions import ResourceNotFoundError except ImportError: # This is handled in azure_rm_common diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevice.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevice.py index f05198506..be007b8d8 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevice.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevice.py @@ -108,6 +108,8 @@ EXAMPLES = ''' name: Testing hub_policy_name: iothubowner hub_policy_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + primary_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + secondary_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" - name: Create Azure IoT Edge device azure_rm_iotdevice: @@ -115,7 +117,9 @@ EXAMPLES = ''' name: Testing hub_policy_name: iothubowner hub_policy_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" - edge_enabled: yes + primary_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + secondary_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + edge_enabled: true - name: Create Azure IoT Hub device with device twin properties and tag azure_rm_iotdevice: @@ -123,13 +127,15 @@ EXAMPLES = ''' name: Testing hub_policy_name: iothubowner hub_policy_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + primary_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + secondary_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" twin_tags: - location: - country: US - city: Redmond - sensor: humidity + location: + country: US + city: Redmond + sensor: humidity desired: - period: 100 + period: 100 ''' RETURN = ''' @@ -219,16 +225,12 @@ device: } ''' # NOQA -import json -import copy import re -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, format_resource_id -from ansible.module_utils.common.dict_transformations import _snake_to_camel +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: - from msrestazure.tools import parse_resource_id - from msrestazure.azure_exceptions import CloudError + from azure.iot.hub import IoTHubRegistryManager except ImportError: # This is handled in azure_rm_common pass @@ -272,14 +274,7 @@ class AzureRMIoTDevice(AzureRMModuleBase): self.secondary_key = None self._base_url = None - self._mgmt_client = None - self.query_parameters = { - 'api-version': '2018-06-30' - } - self.header_parameters = { - 'Content-Type': 'application/json; charset=utf-8', - 'accept-language': 'en-US' - } + self.mgmt_client = None super(AzureRMIoTDevice, self).__init__(self.module_arg_spec, supports_check_mode=True) def exec_module(self, **kwargs): @@ -288,38 +283,23 @@ class AzureRMIoTDevice(AzureRMModuleBase): setattr(self, key, kwargs[key]) self._base_url = '{0}.azure-devices.net'.format(self.hub) - config = { - 'base_url': self._base_url, - 'key': self.hub_policy_key, - 'policy': self.hub_policy_name - } - self._mgmt_client = self.get_data_svc_client(**config) + + connect_str = "HostName={0};SharedAccessKeyName={1};SharedAccessKey={2}".format(self._base_url, self.hub_policy_name, self.hub_policy_key) + self.mgmt_client = IoTHubRegistryManager.from_connection_string(connect_str) changed = False + update_changed = False device = self.get_device() + + if self.status is not None and not self.status: + device['status'] = 'disabled' + if self.state == 'present': if not device: changed = True - auth = {'type': _snake_to_camel(self.auth_method)} - if self.auth_method == 'self_signed': - auth['x509Thumbprint'] = { - 'primaryThumbprint': self.primary_key, - 'secondaryThumbprint': self.secondary_key - } - elif self.auth_method == 'sas': - auth['symmetricKey'] = { - 'primaryKey': self.primary_key, - 'secondaryKey': self.secondary_key - } - device = { - 'deviceId': self.name, - 'capabilities': {'iotEdge': self.edge_enabled or False}, - 'authentication': auth - } - if self.status is not None and not self.status: - device['status'] = 'disabled' else: + update_changed = True if self.edge_enabled is not None and self.edge_enabled != device['capabilities']['iotEdge']: changed = True device['capabilities']['iotEdge'] = self.edge_enabled @@ -328,9 +308,14 @@ class AzureRMIoTDevice(AzureRMModuleBase): if status != device['status']: changed = True device['status'] = status - if changed and not self.check_mode: - device = self.create_or_update_device(device) + if not self.check_mode: + if changed and update_changed: + device = self.update_device(device) + elif changed: + device = self.create_device() + twin = self.get_twin() + if twin: if not twin.get('tags'): twin['tags'] = dict() @@ -340,18 +325,26 @@ class AzureRMIoTDevice(AzureRMModuleBase): if self.desired and not self.is_equal(self.desired, twin['properties']['desired']): twin_change = True if twin_change and not self.check_mode: - self.update_twin(twin) + twin_dict = dict() + twin_dict['tags'] = self.twin_tags + twin_dict['properties'] = dict() + twin_dict['properties']['desired'] = self.desired + + twin = self.update_twin(twin_dict) + changed = changed or twin_change device['tags'] = twin.get('tags') or dict() - device['properties'] = twin['properties'] + device['properties'] = twin.get('properties') or dict() device['modules'] = self.list_device_modules() elif self.twin_tags or self.desired: self.fail("Device twin is not supported in IoT Hub with basic tier.") - elif device: + else: if not self.check_mode: - self.delete_device(device['etag']) - changed = True - device = None + if device: + changed = True + self.delete_device(device['etag']) + else: + changed = True self.results = device or dict() self.results['changed'] = changed return self.results @@ -376,83 +369,140 @@ class AzureRMIoTDevice(AzureRMModuleBase): original[key] = updated_value return not changed - def create_or_update_device(self, device): + def update_device(self, device): + response = None try: - url = '/devices/{0}'.format(self.name) - headers = copy.copy(self.header_parameters) - if device.get('etag'): - headers['If-Match'] = '"{0}"'.format(device['etag']) - request = self._mgmt_client.put(url, self.query_parameters) - response = self._mgmt_client.send(request=request, headers=headers, content=device) - if response.status_code not in [200, 201, 202]: - raise CloudError(response) - return json.loads(response.text) + if self.auth_method == 'sas': + response = self.mgmt_client.update_device_with_sas(self.name, device['etag'], + self.primary_key, self.secondary_key, self.status, iot_edge=self.edge_enabled) + elif self.auth_method == 'self_signed': + response = self.mgmt_client.update_device_with_certificate_authority(self.name, self.status, iot_edge=self.edge_enabled) + elif self.auth_method == 'certificate_authority': + response = self.mgmt_client.update_device_with_x509(self.name, device['etag'], self.primary_thumbprint, + self.secondary_thumbprint, self.status, iot_edge=self.edge_enabled) + + return self.format_item(response) except Exception as exc: - if exc.status_code in [403] and self.edge_enabled: - self.fail('Edge device is not supported in IoT Hub with Basic tier.') - else: - self.fail('Error when creating or updating IoT Hub device {0}: {1}'.format(self.name, exc.message or str(exc))) + self.fail('Error when creating or updating IoT Hub device {0}: {1}'.format(self.name, exc.message or str(exc))) + + def create_device(self): + response = None + try: + if self.auth_method == 'sas': + response = self.mgmt_client.create_device_with_sas(self.name, self.primary_key, self.secondary_key, self.status, iot_edge=self.edge_enabled) + elif self.auth_method == 'self_signed': + response = self.mgmt_client.create_device_with_certificate_authority(self.name, self.status, iot_edge=self.edge_enabled) + elif self.auth_method == 'certificate_authority': + response = self.mgmt_client.create_device_with_x509(self.name, + self.primary_thumbprint, self.secondary_thumbprint, self.status, iot_edge=self.edge_enabled) + + return self.format_item(response) + except Exception as exc: + self.fail('Error when creating or updating IoT Hub device {0}: {1}'.format(self.name, exc.message or str(exc))) def delete_device(self, etag): try: - url = '/devices/{0}'.format(self.name) - headers = copy.copy(self.header_parameters) - headers['If-Match'] = '"{0}"'.format(etag) - request = self._mgmt_client.delete(url, self.query_parameters) - response = self._mgmt_client.send(request=request, headers=headers) - if response.status_code not in [204]: - raise CloudError(response) + response = self.mgmt_client.delete_device(self.name, etag=etag) + return response + except Exception as exc: self.fail('Error when deleting IoT Hub device {0}: {1}'.format(self.name, exc.message or str(exc))) def get_device(self): try: - url = '/devices/{0}'.format(self.name) - device = self._https_get(url, self.query_parameters, self.header_parameters) - return device + response = self.mgmt_client.get_device(self.name) + + response = self.format_item(response) + return response except Exception as exc: - if exc.status_code in [404]: - return None - else: - self.fail('Error when getting IoT Hub device {0}: {1}'.format(self.name, exc.message or str(exc))) + self.log('Error when getting IoT Hub device {0}: {1}'.format(self.name, exc)) def get_twin(self): try: - url = '/twins/{0}'.format(self.name) - return self._https_get(url, self.query_parameters, self.header_parameters) + response = self.mgmt_client.get_twin(self.name) + return self.format_twin(response) except Exception as exc: - if exc.status_code in [403]: - # The Basic sku has nothing to to with twin - return None - else: - self.fail('Error when getting IoT Hub device {0} twin: {1}'.format(self.name, exc.message or str(exc))) + self.fail('Error when getting IoT Hub device {0} twin: {1}'.format(self.name, exc.message or str(exc))) def update_twin(self, twin): try: - url = '/twins/{0}'.format(self.name) - headers = copy.copy(self.header_parameters) - headers['If-Match'] = '"{0}"'.format(twin['etag']) - request = self._mgmt_client.patch(url, self.query_parameters) - response = self._mgmt_client.send(request=request, headers=headers, content=twin) - if response.status_code not in [200]: - raise CloudError(response) - return json.loads(response.text) + response = self.mgmt_client.update_twin(self.name, twin) + + return self.format_twin(response) except Exception as exc: self.fail('Error when creating or updating IoT Hub device twin {0}: {1}'.format(self.name, exc.message or str(exc))) def list_device_modules(self): try: - url = '/devices/{0}/modules'.format(self.name) - return self._https_get(url, self.query_parameters, self.header_parameters) + response = None + response = self.mgmt_client.get_modules(self.name) + + response = [self.format_item(item) for item in response] + return response + except Exception as exc: - self.fail('Error when listing IoT Hub device {0} modules: {1}'.format(self.name, exc.message or str(exc))) - - def _https_get(self, url, query_parameters, header_parameters): - request = self._mgmt_client.get(url, query_parameters) - response = self._mgmt_client.send(request=request, headers=header_parameters, content=None) - if response.status_code not in [200]: - raise CloudError(response) - return json.loads(response.text) + if hasattr(exc, 'message'): + pass + else: + self.fail('Error when listing IoT Hub devices in {0}: {1}'.format(self.hub, exc)) + + def format_twin(self, item): + if not item: + return None + format_twin = dict( + device_id=item.device_id, + module_id=item.module_id, + tags=item.tags, + properties=dict(), + etag=item.etag, + version=item.version, + device_etag=item.device_etag, + status=item.status, + cloud_to_device_message_count=item.cloud_to_device_message_count, + authentication_type=item.authentication_type, + ) + if item.properties is not None: + format_twin['properties']['desired'] = item.properties.desired + format_twin['properties']['reported'] = item.properties.reported + + return format_twin + + def format_item(self, item): + if not item: + return None + format_item = dict( + authentication=dict(), + capabilities=dict(), + cloudToDeviceMessageCount=item.cloud_to_device_message_count, + connectionState=item.connection_state, + connectionStateUpdatedTime=item.connection_state_updated_time, + deviceId=item.device_id, + etag=item.etag, + generationId=item.generation_id, + lastActivityTime=item.last_activity_time + ) + if hasattr(item, 'status_updated_time'): + format_item['statusUpdatedTime'] = item.status_updated_time + if hasattr(item, 'status_reason'): + format_item['status_reason'] = item.status_reason + if hasattr(item, 'status'): + format_item['status'] = item.status + if hasattr(item, 'modules'): + format_item['modules'] = item.modules + if item.authentication: + format_item['authentication']['symmetricKey'] = dict() + format_item['authentication']['symmetricKey']['primaryKey'] = item.authentication.symmetric_key.primary_key + format_item['authentication']['symmetricKey']['secondaryKey'] = item.authentication.symmetric_key.secondary_key + + format_item['authentication']['type'] = item.authentication.type + format_item['authentication']["x509Thumbprint"] = dict() + format_item['authentication']["x509Thumbprint"]["primaryThumbprint"] = item.authentication.x509_thumbprint.primary_thumbprint + format_item['authentication']["x509Thumbprint"]['secondaryThumbprint'] = item.authentication.x509_thumbprint.secondary_thumbprint + format_item['capabilities'] = dict() + if hasattr(item, 'capabilities') and item.capabilities is not None: + format_item['capabilities']["iotEdge"] = item.capabilities.iot_edge + + return format_item def main(): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevice_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevice_info.py index ef82bdc17..359192f47 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevice_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevice_info.py @@ -69,9 +69,15 @@ EXAMPLES = ''' hub_policy_name: registryRead hub_policy_key: XXXXXXXXXXXXXXXXXXXX +- name: Query devices + azure_rm_iotdevice_info: + hub: "hub{{ rpfx }}" + query: "SELECT * FROM devices" + hub_policy_name: "{{ registry_write_name }}" + hub_policy_key: "{{ registry_write_key }}" + - name: Query all device modules in an IoT Hub azure_rm_iotdevice_info: - query: "SELECT * FROM devices.modules" hub: MyIoTHub hub_policy_name: registryRead hub_policy_key: XXXXXXXXXXXXXXXXXXXX @@ -170,14 +176,10 @@ iot_devices: } ''' # NOQA -import json - -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, format_resource_id -from ansible.module_utils.common.dict_transformations import _snake_to_camel, _camel_to_snake +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: - from msrestazure.tools import parse_resource_id - from msrestazure.azure_exceptions import CloudError + from azure.iot.hub import IoTHubRegistryManager except ImportError: # This is handled in azure_rm_common pass @@ -208,16 +210,11 @@ class AzureRMIoTDeviceFacts(AzureRMModuleBase): self.hub_policy_name = None self.hub_policy_key = None self.top = None + self.query = None - self._mgmt_client = None + self.mgmt_client = None self._base_url = None - self.query_parameters = { - 'api-version': '2018-06-30' - } - self.header_parameters = { - 'Content-Type': 'application/json; charset=utf-8', - 'accept-language': 'en-US' - } + super(AzureRMIoTDeviceFacts, self).__init__(self.module_arg_spec, supports_check_mode=True) def exec_module(self, **kwargs): @@ -226,21 +223,16 @@ class AzureRMIoTDeviceFacts(AzureRMModuleBase): setattr(self, key, kwargs[key]) self._base_url = '{0}.azure-devices.net'.format(self.hub) - config = { - 'base_url': self._base_url, - 'key': self.hub_policy_key, - 'policy': self.hub_policy_name - } - if self.top: - self.query_parameters['top'] = self.top - self._mgmt_client = self.get_data_svc_client(**config) + + connect_str = "HostName={0};SharedAccessKeyName={1};SharedAccessKey={2}".format(self._base_url, self.hub_policy_name, self.hub_policy_key) + self.mgmt_client = IoTHubRegistryManager.from_connection_string(connect_str) response = [] if self.module_id: response = [self.get_device_module()] elif self.name: response = [self.get_device()] - elif self.query: + elif self.query is not None: response = self.hub_query() else: response = self.list_devices() @@ -248,56 +240,140 @@ class AzureRMIoTDeviceFacts(AzureRMModuleBase): self.results['iot_devices'] = response return self.results - def hub_query(self): - try: - url = '/devices/query' - request = self._mgmt_client.post(url, self.query_parameters) - query = { - 'query': self.query - } - response = self._mgmt_client.send(request=request, headers=self.header_parameters, content=query) - if response.status_code not in [200]: - raise CloudError(response) - return json.loads(response.text) - except Exception as exc: - self.fail('Error when running query "{0}" in IoT Hub {1}: {2}'.format(self.query, self.hub, exc.message or str(exc))) - def get_device(self): try: - url = '/devices/{0}'.format(self.name) - device = self._https_get(url, self.query_parameters, self.header_parameters) - device['modules'] = self.list_device_modules() - return device + response = self.mgmt_client.get_device(self.name) + + response = self.format_item(response) + return response except Exception as exc: - self.fail('Error when getting IoT Hub device {0}: {1}'.format(self.name, exc.message or str(exc))) + self.fail('Error when getting IoT Hub device {0}: {1}'.format(self.name, exc)) def get_device_module(self): try: - url = '/devices/{0}/modules/{1}'.format(self.name, self.module_id) - return self._https_get(url, self.query_parameters, self.header_parameters) + response = self.mgmt_client.get_module(self.name, self.module_id) + return self.format_module(response) except Exception as exc: - self.fail('Error when getting IoT Hub device {0}: {1}'.format(self.name, exc.message or str(exc))) + self.fail('Error when getting IoT Hub device {0}: {1}'.format(self.name, exc)) def list_device_modules(self): try: - url = '/devices/{0}/modules'.format(self.name) - return self._https_get(url, self.query_parameters, self.header_parameters) + response = self.mgmt_client.get_modules(self.name) + + return [self.format_module(item) for item in response] except Exception as exc: - self.fail('Error when getting IoT Hub device {0}: {1}'.format(self.name, exc.message or str(exc))) + self.fail('Error when getting IoT Hub device {0}: {1}'.format(self.name, exc)) def list_devices(self): try: - url = '/devices' - return self._https_get(url, self.query_parameters, self.header_parameters) + response = None + response = self.mgmt_client.get_devices(max_number_of_devices=1000) + + response = [self.format_item(item) for item in response] + if self.top is not None: + return response[self.top - 1] + else: + return response + except Exception as exc: + if hasattr(exc, 'message'): + pass + else: + self.fail('Error when listing IoT Hub devices in {0}: {1}'.format(self.hub, exc)) + + def hub_query(self): + try: + response = None + response = self.mgmt_client.query_iot_hub(dict(query=self.query)) + + return [self.format_twin(item) for item in response.items] + except Exception as exc: - self.fail('Error when listing IoT Hub devices in {0}: {1}'.format(self.hub, exc.message or str(exc))) - - def _https_get(self, url, query_parameters, header_parameters): - request = self._mgmt_client.get(url, query_parameters) - response = self._mgmt_client.send(request=request, headers=header_parameters, content=None) - if response.status_code not in [200]: - raise CloudError(response) - return json.loads(response.text) + if hasattr(exc, 'message'): + pass + else: + self.fail('Error when listing IoT Hub devices in {0}: {1}'.format(self.hub, exc)) + + def format_module(self, item): + if not item: + return None + format_item = dict( + authentication=dict(), + cloudToDeviceMessageCount=item.cloud_to_device_message_count, + connectionState=item.connection_state, + connectionStateUpdatedTime=item.connection_state_updated_time, + deviceId=item.device_id, + etag=item.etag, + generationId=item.generation_id, + lastActivityTime=item.last_activity_time, + managedBy=item.managed_by, + moduleId=item.module_id + ) + if item.authentication: + format_item['authentication']['symmetricKey'] = dict() + format_item['authentication']['symmetricKey']['primaryKey'] = item.authentication.symmetric_key.primary_key + format_item['authentication']['symmetricKey']['secondaryKey'] = item.authentication.symmetric_key.secondary_key + + format_item['authentication']['type'] = item.authentication.type + format_item['authentication']["x509Thumbprint"] = dict() + format_item['authentication']["x509Thumbprint"]["primaryThumbprint"] = item.authentication.x509_thumbprint.primary_thumbprint + format_item['authentication']["x509Thumbprint"]['secondaryThumbprint'] = item.authentication.x509_thumbprint.secondary_thumbprint + + return format_item + + def format_item(self, item): + if not item: + return None + format_item = dict( + authentication=dict(), + capabilities=dict(), + cloudToDeviceMessageCount=item.cloud_to_device_message_count, + connectionState=item.connection_state, + connectionStateUpdatedTime=item.connection_state_updated_time, + deviceId=item.device_id, + etag=item.etag, + generationId=item.generation_id, + lastActivityTime=item.last_activity_time, + status=item.status, + statusReason=item.status_reason + ) + if hasattr(item, 'status_updated_time'): + format_item['statusUpdatedTime'] = item.status_updated_time + if hasattr(item, 'modules'): + format_item['modules'] = item.modules + if item.authentication: + format_item['authentication']['symmetricKey'] = dict() + format_item['authentication']['symmetricKey']['primaryKey'] = item.authentication.symmetric_key.primary_key + format_item['authentication']['symmetricKey']['secondaryKey'] = item.authentication.symmetric_key.secondary_key + + format_item['authentication']['type'] = item.authentication.type + format_item['authentication']["x509Thumbprint"] = dict() + format_item['authentication']["x509Thumbprint"]["primaryThumbprint"] = item.authentication.x509_thumbprint.primary_thumbprint + format_item['authentication']["x509Thumbprint"]['secondaryThumbprint'] = item.authentication.x509_thumbprint.secondary_thumbprint + if item.capabilities: + format_item['capabilities']["iotEdge"] = item.capabilities.iot_edge + + return format_item + + def format_twin(self, item): + if not item: + return None + format_twin = dict( + device_id=item.device_id, + module_id=item.module_id, + tags=item.tags, + properties=dict(), + etag=item.etag, + version=item.version, + device_etag=item.device_etag, + status=item.status, + cloud_to_device_message_count=item.cloud_to_device_message_count, + authentication_type=item.authentication_type, + ) + if item.properties is not None: + format_twin['properties']['desired'] = item.properties.desired + format_twin['properties']['reported'] = item.properties.reported + + return format_twin def main(): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevicemodule.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevicemodule.py index d23435130..2f2ad679d 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevicemodule.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevicemodule.py @@ -103,6 +103,8 @@ EXAMPLES = ''' device: mydevice hub_policy_name: iothubowner hub_policy_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + primary_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + secondary_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" - name: Create Azure IoT Edge device module azure_rm_iotdevice: @@ -111,7 +113,9 @@ EXAMPLES = ''' name: Testing hub_policy_name: iothubowner hub_policy_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" - edge_enabled: yes + primary_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + secondary_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + edge_enabled: true - name: Create Azure IoT Hub device module with module twin properties and tag azure_rm_iotdevice: @@ -120,13 +124,15 @@ EXAMPLES = ''' device: mydevice hub_policy_name: iothubowner hub_policy_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + primary_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + secondary_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" twin_tags: - location: - country: US - city: Redmond - sensor: humidity + location: + country: US + city: Redmond + sensor: humidity desired: - period: 100 + period: 100 ''' RETURN = ''' @@ -159,16 +165,12 @@ module: } ''' # NOQA -import json -import copy import re -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, format_resource_id -from ansible.module_utils.common.dict_transformations import _snake_to_camel +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: - from msrestazure.tools import parse_resource_id - from msrestazure.azure_exceptions import CloudError + from azure.iot.hub import IoTHubRegistryManager except ImportError: # This is handled in azure_rm_common pass @@ -208,16 +210,11 @@ class AzureRMIoTDeviceModule(AzureRMModuleBase): self.auth_method = None self.primary_key = None self.secondary_key = None + self.managed_by = None + self.etag = None self._base_url = None - self._mgmt_client = None - self.query_parameters = { - 'api-version': '2018-06-30' - } - self.header_parameters = { - 'Content-Type': 'application/json; charset=utf-8', - 'accept-language': 'en-US' - } + self.mgmt_client = None super(AzureRMIoTDeviceModule, self).__init__(self.module_arg_spec, supports_check_mode=True) def exec_module(self, **kwargs): @@ -226,12 +223,9 @@ class AzureRMIoTDeviceModule(AzureRMModuleBase): setattr(self, key, kwargs[key]) self._base_url = '{0}.azure-devices.net'.format(self.hub) - config = { - 'base_url': self._base_url, - 'key': self.hub_policy_key, - 'policy': self.hub_policy_name - } - self._mgmt_client = self.get_data_svc_client(**config) + connect_str = "HostName={0};SharedAccessKeyName={1};SharedAccessKey={2}".format(self._base_url, self.hub_policy_name, self.hub_policy_key) + + self.mgmt_client = IoTHubRegistryManager.from_connection_string(connect_str) changed = False @@ -239,24 +233,11 @@ class AzureRMIoTDeviceModule(AzureRMModuleBase): if self.state == 'present': if not module: changed = True - auth = {'type': _snake_to_camel(self.auth_method)} - if self.auth_method == 'self_signed': - auth['x509Thumbprint'] = { - 'primaryThumbprint': self.primary_key, - 'secondaryThumbprint': self.secondary_key - } - elif self.auth_method == 'sas': - auth['symmetricKey'] = { - 'primaryKey': self.primary_key, - 'secondaryKey': self.secondary_key - } - module = { - 'deviceId': self.device, - 'moduleId': self.name, - 'authentication': auth - } - if changed and not self.check_mode: - module = self.create_or_update_module(module) + if not self.check_mode: + module = self.create_module() + else: + self.etag = module.get('etag') + twin = self.get_twin() if not twin.get('tags'): twin['tags'] = dict() @@ -267,15 +248,20 @@ class AzureRMIoTDeviceModule(AzureRMModuleBase): self.module.warn('desired') twin_change = True if twin_change and not self.check_mode: - twin = self.update_twin(twin) + twin_dict = dict() + twin_dict['tags'] = self.twin_tags + twin_dict['properties'] = dict() + twin_dict['properties']['desired'] = self.desired + twin = self.update_twin(twin_dict) + changed = changed or twin_change module['tags'] = twin.get('tags') or dict() - module['properties'] = twin['properties'] - elif module: - if not self.check_mode: - self.delete_module(module['etag']) - changed = True - module = None + module['properties'] = twin.get('properties') or dict() + else: + if module and not self.check_mode: + self.delete_module() + changed = True + self.results = module or dict() self.results['changed'] = changed return self.results @@ -300,65 +286,114 @@ class AzureRMIoTDeviceModule(AzureRMModuleBase): original[key] = updated_value return not changed - def create_or_update_module(self, module): + def update_module(self): + response = None + try: + if self.auth_method == 'sas': + response = self.mgmt_client.update_module_with_sas(self.device, self.name, self.managed_by, self.etag, self.primary_key, self.secondary_key) + elif self.auth_method == 'self_signed': + response = self.mgmt_client.update_module_with_certificate_authority(self.device, self.name, self.managed_by, self.etag) + elif self.auth_method == 'certificate_authority': + response = self.mgmt_client.update_module_with_x509(self.device, + self.name, self.managed_by, self.etag, self.primary_thumbprint, self.secondary_thumbprint) + + return self.format_module(response) + except Exception as exc: + if exc.status_code in [403] and self.edge_enabled: + self.fail('Edge device is not supported in IoT Hub with Basic tier.') + else: + self.fail('Error when creating or updating IoT Hub device {0}: {1}'.format(self.name, exc.message or str(exc))) + + def create_module(self): + response = None try: - url = '/devices/{0}/modules/{1}'.format(self.device, self.name) - headers = copy.copy(self.header_parameters) - if module.get('etag'): - headers['If-Match'] = '"{0}"'.format(module['etag']) - request = self._mgmt_client.put(url, self.query_parameters) - response = self._mgmt_client.send(request=request, headers=headers, content=module) - if response.status_code not in [200, 201]: - raise CloudError(response) - return json.loads(response.text) + if self.auth_method == 'sas': + response = self.mgmt_client.create_module_with_sas(self.device, self.name, self.managed_by, self.primary_key, self.secondary_key) + elif self.auth_method == 'self_signed': + response = self.mgmt_client.create_module_with_certificate_authority(self.device, self.name, self.managed_by) + elif self.auth_method == 'certificate_authority': + response = self.mgmt_client.create_module_with_x509(self.device_id, + self.name, self.managed_by, self.primary_thumbprint, self.secondary_thumbprint) + + return self.format_module(response) except Exception as exc: self.fail('Error when creating or updating IoT Hub device {0}: {1}'.format(self.name, exc.message or str(exc))) def delete_module(self, etag): try: - url = '/devices/{0}/modules/{1}'.format(self.device, self.name) - headers = copy.copy(self.header_parameters) - headers['If-Match'] = '"{0}"'.format(etag) - request = self._mgmt_client.delete(url, self.query_parameters) - response = self._mgmt_client.send(request=request, headers=headers) - if response.status_code not in [204]: - raise CloudError(response) + response = self.mgmt_client.delete_module(self.device, self.name) + return response except Exception as exc: self.fail('Error when deleting IoT Hub device {0}: {1}'.format(self.name, exc.message or str(exc))) def get_module(self): try: - url = '/devices/{0}/modules/{1}'.format(self.device, self.name) - return self._https_get(url, self.query_parameters, self.header_parameters) + response = self.mgmt_client.get_module(self.device, self.name) + return self.format_module(response) except Exception: return None def get_twin(self): try: - url = '/twins/{0}/modules/{1}'.format(self.device, self.name) - return self._https_get(url, self.query_parameters, self.header_parameters) + response = self.mgmt_client.get_twin(self.device) + return self.format_twin(response) except Exception as exc: self.fail('Error when getting IoT Hub device {0} module twin {1}: {2}'.format(self.device, self.name, exc.message or str(exc))) def update_twin(self, twin): try: - url = '/twins/{0}/modules/{1}'.format(self.device, self.name) - headers = copy.copy(self.header_parameters) - headers['If-Match'] = twin['etag'] - request = self._mgmt_client.patch(url, self.query_parameters) - response = self._mgmt_client.send(request=request, headers=headers, content=twin) - if response.status_code not in [200]: - raise CloudError(response) - return json.loads(response.text) + response = self.mgmt_client.update_twin(self.device, twin) + return self.format_twin(response) except Exception as exc: self.fail('Error when creating or updating IoT Hub device {0} module twin {1}: {2}'.format(self.device, self.name, exc.message or str(exc))) - def _https_get(self, url, query_parameters, header_parameters): - request = self._mgmt_client.get(url, query_parameters) - response = self._mgmt_client.send(request=request, headers=header_parameters, content=None) - if response.status_code not in [200]: - raise CloudError(response) - return json.loads(response.text) + def format_module(self, item): + if not item: + return None + format_item = dict( + authentication=dict(), + cloudToDeviceMessageCount=item.cloud_to_device_message_count, + connectionState=item.connection_state, + connectionStateUpdatedTime=item.connection_state_updated_time, + deviceId=item.device_id, + etag=item.etag, + generationId=item.generation_id, + lastActivityTime=item.last_activity_time, + managedBy=item.managed_by, + moduleId=item.module_id + ) + if item.authentication: + format_item['authentication']['symmetricKey'] = dict() + format_item['authentication']['symmetricKey']['primaryKey'] = item.authentication.symmetric_key.primary_key + format_item['authentication']['symmetricKey']['secondaryKey'] = item.authentication.symmetric_key.secondary_key + + format_item['authentication']['type'] = item.authentication.type + format_item['authentication']["x509Thumbprint"] = dict() + format_item['authentication']["x509Thumbprint"]["primaryThumbprint"] = item.authentication.x509_thumbprint.primary_thumbprint + format_item['authentication']["x509Thumbprint"]['secondaryThumbprint'] = item.authentication.x509_thumbprint.secondary_thumbprint + + return format_item + + def format_twin(self, item): + if not item: + return None + format_twin = dict( + device_id=item.device_id, + module_id=item.module_id, + tags=item.tags, + properties=dict(), + etag=item.etag, + version=item.version, + device_etag=item.device_etag, + status=item.status, + cloud_to_device_message_count=item.cloud_to_device_message_count, + authentication_type=item.authentication_type, + ) + if item.properties is not None: + format_twin['properties']['desired'] = item.properties.desired + format_twin['properties']['reported'] = item.properties.reported + + return format_twin def main(): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iothub.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iothub.py index daf59783a..931cede97 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iothub.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iothub.py @@ -204,15 +204,15 @@ EXAMPLES = ''' resource_group: myResourceGroup name: Testing routing_endpoints: - - connection_string: "Endpoint=sb://qux.servicebus.windows.net/;SharedAccessKeyName=quux;SharedAccessKey=****;EntityPath=myQueue" - name: foo - resource_type: queue - resource_group: myResourceGroup1 + - connection_string: "Endpoint=sb://qux.servicebus.windows.net/;SharedAccessKeyName=quux;SharedAccessKey=****;EntityPath=myQueue" + name: foo + resource_type: queue + resource_group: myResourceGroup1 routes: - - name: bar - source: device_messages - endpoint_name: foo - enabled: yes + - name: bar + source: device_messages + endpoint_name: foo + enabled: true ''' RETURN = ''' @@ -507,16 +507,10 @@ routes: sample: "true" ''' # NOQA -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, format_resource_id +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from ansible.module_utils.common.dict_transformations import _snake_to_camel, _camel_to_snake import re -try: - from msrestazure.tools import parse_resource_id -except ImportError: - # This is handled in azure_rm_common - pass - ip_filter_spec = dict( name=dict(type='str', required=True), diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iothub_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iothub_info.py index 22b2335f4..64706a71d 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iothub_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iothub_info.py @@ -70,22 +70,22 @@ author: ''' EXAMPLES = ''' - - name: Get facts for one IoT Hub - azure_rm_iothub_info: - name: Testing - resource_group: myResourceGroup +- name: Get facts for one IoT Hub + azure_rm_iothub_info: + name: Testing + resource_group: myResourceGroup - - name: Get facts for all IoT Hubs - azure_rm_iothub_info: +- name: Get facts for all IoT Hubs + azure_rm_iothub_info: - - name: Get facts for all IoT Hubs in a specific resource group - azure_rm_iothub_info: - resource_group: myResourceGroup +- name: Get facts for all IoT Hubs in a specific resource group + azure_rm_iothub_info: + resource_group: myResourceGroup - - name: Get facts by tags - azure_rm_iothub_info: - tags: - - testing +- name: Get facts by tags + azure_rm_iothub_info: + tags: + - testing ''' RETURN = ''' @@ -396,7 +396,7 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common from ansible.module_utils.common.dict_transformations import _camel_to_snake try: - from msrestazure.tools import parse_resource_id + from azure.mgmt.core.tools import parse_resource_id except Exception: # handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iothubconsumergroup.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iothubconsumergroup.py index 21dde7fbb..fca748d0b 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iothubconsumergroup.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iothubconsumergroup.py @@ -43,6 +43,7 @@ options: description: - Name of the consumer group. type: str + required: True extends_documentation_fragment: - azure.azcollection.azure - azure.azcollection.azure_tags @@ -76,15 +77,7 @@ name: type: str ''' # NOQA -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, format_resource_id -from ansible.module_utils.common.dict_transformations import _snake_to_camel, _camel_to_snake -import re - -try: - from msrestazure.tools import parse_resource_id -except ImportError: - # This is handled in azure_rm_common - pass +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase class AzureRMIoTHubConsumerGroup(AzureRMModuleBase): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_ipgroup.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_ipgroup.py index 717923770..1e464ced2 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_ipgroup.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_ipgroup.py @@ -162,8 +162,7 @@ state: ''' from ansible.module_utils.basic import _load_params -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, HAS_AZURE, \ - format_resource_id, normalize_location_name +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, normalize_location_name try: from azure.core.exceptions import ResourceNotFoundError diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_ipgroup_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_ipgroup_info.py index 3ed6423a6..21a922c3b 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_ipgroup_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_ipgroup_info.py @@ -84,7 +84,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError - from azure.common import AzureMissingResourceHttpError, AzureHttpError except Exception: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvault.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvault.py index f117b380c..efeddaacc 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvault.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvault.py @@ -21,28 +21,35 @@ options: description: - The name of the Resource Group to which the server belongs. required: True + type: str vault_name: description: - Name of the vault. required: True + type: str location: description: - Resource location. If not set, location from the resource group will be used as default. + type: str vault_tenant: description: - The Azure Active Directory tenant ID that should be used for authenticating requests to the key vault. + type: str sku: description: - SKU details. + type: dict suboptions: family: description: - SKU family name. + type: str required: True name: description: - SKU name to specify whether the key vault is a standard vault or a premium vault. required: True + type: str choices: - 'standard' - 'premium' @@ -50,23 +57,30 @@ options: description: - An array of 0 to 16 identities that have access to the key vault. - All identities in the array must use the same tenant ID as the key vault's tenant ID. + type: list + elements: dict suboptions: tenant_id: description: - The Azure Active Directory tenant ID that should be used for authenticating requests to the key vault. - Current keyvault C(tenant_id) value will be used if not specified. + type: str object_id: description: - The object ID of a user, service principal or security group in the Azure Active Directory tenant for the vault. - The object ID must be unique for the list of access policies. - Please note this is not application id. Object id can be obtained by running "az ad sp show --id <application id>". + type: str required: True application_id: description: - Application ID of the client making request on behalf of a principal. + type: str keys: description: - List of permissions to keys. + type: list + elements: str choices: - 'encrypt' - 'decrypt' @@ -87,6 +101,8 @@ options: secrets: description: - List of permissions to secrets. + type: list + elements: str choices: - 'get' - 'list' @@ -99,6 +115,8 @@ options: certificates: description: - List of permissions to certificates. + type: list + elements: str choices: - 'get' - 'list' @@ -114,9 +132,13 @@ options: - 'manageissuers' - 'recover' - 'purge' + - 'backup' + - 'restore' storage: description: - List of permissions to storage accounts. + type: list + elements: str enabled_for_deployment: description: - Property to specify whether Azure Virtual Machines are permitted to retrieve certificates stored as secrets from the key vault. @@ -151,6 +173,7 @@ options: description: - Assert the state of the KeyVault. Use C(present) to create or update an KeyVault and C(absent) to delete it. default: present + type: str choices: - absent - present @@ -165,21 +188,21 @@ author: ''' EXAMPLES = ''' - - name: Create instance of Key Vault - azure_rm_keyvault: - resource_group: myResourceGroup - vault_name: samplekeyvault - enabled_for_deployment: yes - vault_tenant: 72f98888-8666-4144-9199-2d7cd0111111 - sku: - name: standard - family: A - access_policies: - - tenant_id: 72f98888-8666-4144-9199-2d7cd0111111 - object_id: 99998888-8666-4144-9199-2d7cd0111111 - keys: - - get - - list +- name: Create instance of Key Vault + azure_rm_keyvault: + resource_group: myResourceGroup + vault_name: samplekeyvault + enabled_for_deployment: true + vault_tenant: 72f98888-8666-4144-9199-2d7cd0111111 + sku: + name: standard + family: A + access_policies: + - tenant_id: 72f98888-8666-4144-9199-2d7cd0111111 + object_id: 99998888-8666-4144-9199-2d7cd0111111 + keys: + - get + - list ''' RETURN = ''' @@ -191,7 +214,6 @@ id: sample: id ''' -import collections import time from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase @@ -199,7 +221,6 @@ try: from azure.core.polling import LROPoller from azure.core.exceptions import ResourceNotFoundError from azure.mgmt.keyvault import KeyVaultManagementClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass @@ -239,10 +260,26 @@ class AzureRMVaults(AzureRMModuleBase): object_id=dict(type='str', required=True), application_id=dict(type='str'), # FUTURE: add `choices` support once choices supports lists of values - keys=dict(type='list', no_log=True), - secrets=dict(type='list', no_log=True), - certificates=dict(type='list'), - storage=dict(type='list') + keys=dict( + type='list', + elements='str', + no_log=True, + choices=['encrypt', 'decrypt', 'wrapkey', 'unwrapkey', 'sign', 'verify', 'get', + 'list', 'create', 'update', 'import', 'delete', 'backup', 'restore', 'recover', 'purge'] + ), + secrets=dict( + type='list', + elements='str', + no_log=True, + choices=['get', 'list', 'set', 'delete', 'backup', 'restore', 'recover', 'purge'] + ), + certificates=dict( + type='list', + elements='str', + choices=['get', 'list', 'delete', 'create', 'import', 'update', 'managecontacts', + 'getissuers', 'listissuers', 'setissuers', 'deleteissuers', 'manageissuers', 'recover', 'purge', 'backup', 'restore'] + ), + storage=dict(type='list', elements='str') ) ), enabled_for_deployment=dict( diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvault_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvault_info.py index a56a2c378..d7b54515f 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvault_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvault_info.py @@ -40,17 +40,17 @@ author: ''' EXAMPLES = ''' - - name: Get Key Vault by name - azure_rm_keyvault_info: - resource_group: myResourceGroup - name: myVault +- name: Get Key Vault by name + azure_rm_keyvault_info: + resource_group: myResourceGroup + name: myVault - - name: List Key Vaults in specific resource group - azure_rm_keyvault_info: - resource_group: myResourceGroup +- name: List Key Vaults in specific resource group + azure_rm_keyvault_info: + resource_group: myResourceGroup - - name: List Key Vaults in current subscription - azure_rm_keyvault_info: +- name: List Key Vaults in current subscription + azure_rm_keyvault_info: ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultkey.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultkey.py index 985775b9a..54cc6eff6 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultkey.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultkey.py @@ -17,48 +17,62 @@ description: - Such as authentication keys, storage account keys, data encryption keys, .PFX files, and passwords. options: keyvault_uri: - description: - - URI of the keyvault endpoint. - required: true + description: + - URI of the keyvault endpoint. + required: true + type: str key_name: description: - Name of the keyvault key. required: true + type: str key_type: description: - The type of key to create. For valid values, see JsonWebKeyType. Possible values include EC, EC-HSM, RSA, RSA-HSM, oct default: 'RSA' + type: str key_size: description: - The key size in bits. For example 2048, 3072, or 4096 for RSA. + type: int key_attributes: description: - The attributes of a key managed by the key vault service. + type: dict suboptions: enabled: - description: bool + description: + - Whether the key is enabled. + type: bool not_before: description: - not valid before date in UTC ISO format without the Z at the end + type: str expires: description: - not valid after date in UTC ISO format without the Z at the end + type: str curve: description: - Elliptic curve name. For valid values, see JsonWebKeyCurveName. Possible values include P-256, P-384, P-521, P-256K. + type: str byok_file: description: - BYOK file. + type: str pem_file: description: - PEM file. + type: str pem_password: description: - PEM password. + type: str state: description: - Assert the state of the key. Use C(present) to create a key and C(absent) to delete a key. default: present + type: str choices: - absent - present @@ -73,16 +87,16 @@ author: ''' EXAMPLES = ''' - - name: Create a key - azure_rm_keyvaultkey: - key_name: MyKey - keyvault_uri: https://contoso.vault.azure.net/ - - - name: Delete a key - azure_rm_keyvaultkey: - key_name: MyKey - keyvault_uri: https://contoso.vault.azure.net/ - state: absent +- name: Create a key + azure_rm_keyvaultkey: + key_name: MyKey + keyvault_uri: https://contoso.vault.azure.net/ + +- name: Delete a key + azure_rm_keyvaultkey: + key_name: MyKey + keyvault_uri: https://contoso.vault.azure.net/ + state: absent ''' RETURN = ''' @@ -102,14 +116,8 @@ state: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: - import re - import codecs - from azure.keyvault import KeyVaultClient, KeyVaultId, KeyVaultAuthentication - from azure.keyvault.models import KeyAttributes, JsonWebKey - from azure.common.credentials import ServicePrincipalCredentials, get_cli_profile + from azure.keyvault.keys import KeyClient from datetime import datetime - from msrestazure.azure_active_directory import MSIAuthentication - from OpenSSL import crypto except ImportError: # This is handled in azure_rm_common pass @@ -195,8 +203,7 @@ class AzureRMKeyVaultKey(AzureRMModuleBase): # Create key if self.state == 'present' and changed: - results['key_id'] = self.create_key(self.key_name, self.key_type, self.key_size, self.key_attributes, - self.curve, self.tags) + results['key_id'] = self.create_key(self.key_name) self.results['state'] = results self.results['state']['status'] = 'Created' # Delete key @@ -213,153 +220,47 @@ class AzureRMKeyVaultKey(AzureRMModuleBase): return self.results def get_keyvault_client(self): - kv_url = self.azure_auth._cloud_environment.suffixes.keyvault_dns.split('.', 1).pop() - # Don't use MSI credentials if the auth_source isn't set to MSI. The below will Always result in credentials when running on an Azure VM. - if self.module.params['auth_source'] == 'msi': - try: - self.log("Get KeyVaultClient from MSI") - credentials = MSIAuthentication(resource="https://{0}".format(kv_url)) - return KeyVaultClient(credentials) - except Exception: - self.log("Get KeyVaultClient from service principal") - elif (self.module.params['auth_source'] == 'cli' - or (self.module.params['auth_source'] == 'auto' - and self.credentials['client_id'] is None - and self.credentials['secret'] is None)): - try: - profile = get_cli_profile() - credentials, subscription_id, tenant = profile.get_login_credentials( - subscription_id=self.credentials['subscription_id'], resource="https://{0}".format(kv_url)) - return KeyVaultClient(credentials) - except Exception as exc: - self.log("Get KeyVaultClient from service principal") - # self.fail("Failed to load CLI profile {0}.".format(str(exc))) - - # Create KeyVault Client using KeyVault auth class and auth_callback - def auth_callback(server, resource, scope): - if self.credentials['client_id'] is None or self.credentials['secret'] is None: - self.fail('Please specify client_id, secret and tenant to access azure Key Vault.') - - tenant = self.credentials.get('tenant') - if not self.credentials['tenant']: - tenant = "common" - - authcredential = ServicePrincipalCredentials( - client_id=self.credentials['client_id'], - secret=self.credentials['secret'], - tenant=tenant, - cloud_environment=self._cloud_environment, - resource="https://{0}".format(kv_url)) - - token = authcredential.token - return token['token_type'], token['access_token'] - - return KeyVaultClient(KeyVaultAuthentication(auth_callback)) + + return KeyClient(vault_url=self.keyvault_uri, credential=self.azure_auth.azure_credential_track2) def get_key(self, name, version=''): ''' Gets an existing key ''' - key_bundle = self.client.get_key(self.keyvault_uri, name, version) + key_bundle = self.client.get_key(name, version) + if key_bundle: - key_id = KeyVaultId.parse_key_id(key_bundle.key.kid) - return key_id.id + return key_bundle.id - def create_key(self, name, key_type, key_size, key_attributes, curve, tags): + def create_key(self, name): ''' Creates a key ''' - if key_attributes is not None: - k_enabled = key_attributes.get('enabled', True) - k_not_before = key_attributes.get('not_before', None) - k_expires = key_attributes.get('expires', None) + if self.key_attributes is not None: + k_enabled = self.key_attributes.get('enabled', True) + k_not_before = self.key_attributes.get('not_before', None) + k_expires = self.key_attributes.get('expires', None) if k_not_before: k_not_before = datetime.fromisoformat(k_not_before.replace('Z', '+00:00')) if k_expires: k_expires = datetime.fromisoformat(k_expires.replace('Z', '+00:00')) - - key_attributes = KeyAttributes(enabled=k_enabled, not_before=k_not_before, expires=k_expires) - - key_bundle = self.client.create_key(vault_base_url=self.keyvault_uri, key_name=name, kty=key_type, key_size=key_size, - key_attributes=key_attributes, curve=curve, tags=tags) - key_id = KeyVaultId.parse_key_id(key_bundle.key.kid) - return key_id.id + else: + k_enabled = True + k_not_before = None + k_expires = None + + key_bundle = self.client.create_key(name=name, + key_type=self.key_type, + size=self.key_size, + curve=self.curve, + tags=self.tags, + enabled=k_enabled, + not_before=k_not_before, + expires_on=k_expires) + return key_bundle._properties._id def delete_key(self, name): ''' Deletes a key ''' - deleted_key = self.client.delete_key(self.keyvault_uri, name) - key_id = KeyVaultId.parse_key_id(deleted_key.key.kid) - return key_id.id - - def import_key(self, key_name, destination=None, key_ops=None, disabled=False, expires=None, - not_before=None, tags=None, pem_file=None, pem_password=None, byok_file=None): - """ Import a private key. Supports importing base64 encoded private keys from PEM files. - Supports importing BYOK keys into HSM for premium KeyVaults. """ - - def _to_bytes(hex_string): - # zero pads and decodes a hex string - if len(hex_string) % 2: - hex_string = '{0}'.format(hex_string) - return codecs.decode(hex_string, 'hex_codec') - - def _set_rsa_parameters(dest, src): - # map OpenSSL parameter names to JsonWebKey property names - conversion_dict = { - 'modulus': 'n', - 'publicExponent': 'e', - 'privateExponent': 'd', - 'prime1': 'p', - 'prime2': 'q', - 'exponent1': 'dp', - 'exponent2': 'dq', - 'coefficient': 'qi' - } - # regex: looks for matches that fit the following patterns: - # integerPattern: 65537 (0x10001) - # hexPattern: - # 00:a0:91:4d:00:23:4a:c6:83:b2:1b:4c:15:d5:be: - # d8:87:bd:c9:59:c2:e5:7a:f5:4a:e7:34:e8:f0:07: - # The desired match should always be the first component of the match - regex = re.compile(r'([^:\s]*(:[^\:)]+\))|([^:\s]*(:\s*[0-9A-Fa-f]{2})+))') - # regex2: extracts the hex string from a format like: 65537 (0x10001) - regex2 = re.compile(r'(?<=\(0x{1})([0-9A-Fa-f]*)(?=\))') - - key_params = crypto.dump_privatekey(crypto.FILETYPE_TEXT, src).decode('utf-8') - for match in regex.findall(key_params): - comps = match[0].split(':', 1) - name = conversion_dict.get(comps[0], None) - if name: - value = comps[1].replace(' ', '').replace('\n', '').replace(':', '') - try: - value = _to_bytes(value) - except Exception: # pylint:disable=broad-except - # if decoding fails it is because of an integer pattern. Extract the hex - # string and retry - value = _to_bytes(regex2.findall(value)[0]) - setattr(dest, name, value) - - key_attrs = KeyAttributes(not disabled, not_before, expires) - key_obj = JsonWebKey(key_ops=key_ops) - if pem_file: - key_obj.kty = 'RSA' - with open(pem_file, 'r') as f: - pem_data = f.read() - # load private key and prompt for password if encrypted - try: - pem_password = str(pem_password).encode() if pem_password else None - # despite documentation saying password should be a string, it needs to actually - # be UTF-8 encoded bytes - pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, pem_data, pem_password) - except crypto.Error: - pass # wrong password - except TypeError: - pass # no pass provided - _set_rsa_parameters(key_obj, pkey) - elif byok_file: - with open(byok_file, 'rb') as f: - byok_data = f.read() - key_obj.kty = 'RSA-HSM' - key_obj.t = byok_data - - return self.client.import_key( - self.keyvault_uri, key_name, key_obj, destination == 'hsm', key_attrs, tags) + deleted_key = self.client.begin_delete_key(name) + result = self.get_poller_result(deleted_key) + return result.properties._id def main(): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultkey_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultkey_info.py index 7247ec4eb..b59f89b33 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultkey_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultkey_info.py @@ -54,31 +54,31 @@ author: ''' EXAMPLES = ''' - - name: Get latest version of specific key - azure_rm_keyvaultkey_info: - vault_uri: "https://myVault.vault.azure.net" - name: myKey - - - name: List all versions of specific key - azure_rm_keyvaultkey_info: - vault_uri: "https://myVault.vault.azure.net" - name: myKey - version: all - - - name: List specific version of specific key - azure_rm_keyvaultkey_info: - vault_uri: "https://myVault.vault.azure.net" - name: myKey - version: fd2682392a504455b79c90dd04a1bf46 - - - name: List all keys in specific key vault - azure_rm_keyvaultkey_info: - vault_uri: "https://myVault.vault.azure.net" - - - name: List deleted keys in specific key vault - azure_rm_keyvaultkey_info: - vault_uri: "https://myVault.vault.azure.net" - show_deleted_key: True +- name: Get latest version of specific key + azure_rm_keyvaultkey_info: + vault_uri: "https://myVault.vault.azure.net" + name: myKey + +- name: List all versions of specific key + azure_rm_keyvaultkey_info: + vault_uri: "https://myVault.vault.azure.net" + name: myKey + version: all + +- name: List specific version of specific key + azure_rm_keyvaultkey_info: + vault_uri: "https://myVault.vault.azure.net" + name: myKey + version: fd2682392a504455b79c90dd04a1bf46 + +- name: List all keys in specific key vault + azure_rm_keyvaultkey_info: + vault_uri: "https://myVault.vault.azure.net" + +- name: List deleted keys in specific key vault + azure_rm_keyvaultkey_info: + vault_uri: "https://myVault.vault.azure.net" + show_deleted_key: true ''' RETURN = ''' @@ -115,6 +115,7 @@ keyvaults: key: description: - public part of a key. + type: dict contains: n: description: @@ -150,6 +151,7 @@ keyvaults: attributes: description: - Key attributes. + type: dict contains: created: description: @@ -193,10 +195,7 @@ keyvaults: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: - from azure.keyvault import KeyVaultClient, KeyVaultId, KeyVaultAuthentication, KeyId - from azure.keyvault.models import KeyAttributes, JsonWebKey - from azure.common.credentials import ServicePrincipalCredentials, get_cli_profile - from msrestazure.azure_active_directory import MSIAuthentication + from azure.keyvault.keys import KeyClient except ImportError: # This is handled in azure_rm_common pass @@ -204,20 +203,20 @@ except ImportError: def keybundle_to_dict(bundle): return dict( - tags=bundle.tags, - managed=bundle.managed, + tags=bundle.properties.tags, + managed=bundle.properties.managed, attributes=dict( - enabled=bundle.attributes.enabled, - not_before=bundle.attributes.not_before, - expires=bundle.attributes.expires, - created=bundle.attributes.created, - updated=bundle.attributes.updated, - recovery_level=bundle.attributes.recovery_level + enabled=bundle.properties.enabled, + not_before=bundle.properties.not_before, + expires=bundle.properties.expires_on, + created=bundle.properties.created_on, + updated=bundle.properties.updated_on, + recovery_level=bundle.properties.recovery_level ), - kid=bundle.key.kid, - version=KeyVaultId.parse_key_id(bundle.key.kid).version, - type=bundle.key.kty, - permitted_operations=bundle.key.key_ops, + kid=bundle.id, + version=bundle.properties.version, + type=bundle.key_type, + permitted_operations=bundle.key_operations, key=dict( n=bundle.key.n if hasattr(bundle.key, 'n') else None, e=bundle.key.e if hasattr(bundle.key, 'e') else None, @@ -228,35 +227,96 @@ def keybundle_to_dict(bundle): ) +def delete_keybundle_to_dict(bundle): + return dict( + tags=bundle._tags, + managed=bundle._managed, + attributes=dict( + enabled=bundle.enabled, + not_before=bundle.not_before, + expires=bundle.expires_on, + created=bundle.created_on, + updated=bundle.updated_on, + recovery_level=bundle.recovery_level + ), + kid=bundle._id, + version=bundle.version, + ) + + +def delete_properties_to_dict(bundle): + return dict( + tags=bundle.tags, + managed=bundle.managed, + attributes=dict( + enabled=bundle.enabled, + not_before=bundle.not_before, + expires=bundle.expires_on, + created=bundle.created_on, + updated=bundle.updated_on, + recovery_level=bundle.recovery_level + ), + kid=bundle.id, + version=bundle.version, + ) + + def deletedkeybundle_to_dict(bundle): - keybundle = keybundle_to_dict(bundle) - keybundle['recovery_id'] = bundle.recovery_id, - keybundle['scheduled_purge_date'] = bundle.scheduled_purge_date, + keybundle = delete_properties_to_dict(bundle.properties) + keybundle['type'] = bundle.key_type + keybundle['permitted_operations'] = bundle.key_operations + keybundle['recovery_id'] = bundle.recovery_id + keybundle['scheduled_purge_date'] = bundle.scheduled_purge_date keybundle['deleted_date'] = bundle.deleted_date + keybundle['key'] = dict(n=bundle.key.n if hasattr(bundle.key, 'n') else None, + e=bundle.key.e if hasattr(bundle.key, 'e') else None, + crv=bundle.key.crv if hasattr(bundle.key, 'crv') else None, + x=bundle.key.x if hasattr(bundle.key, 'x') else None, + y=bundle.key.y if hasattr(bundle.key, 'y') else None) + keybundle['id'] = bundle.id return keybundle def keyitem_to_dict(keyitem): return dict( - kid=keyitem.kid, - version=KeyVaultId.parse_key_id(keyitem.kid).version, - tags=keyitem.tags, - manged=keyitem.managed, + kid=keyitem._id, + version=keyitem.version, + tags=keyitem._tags, + manged=keyitem._managed, attributes=dict( - enabled=keyitem.attributes.enabled, - not_before=keyitem.attributes.not_before, - expires=keyitem.attributes.expires, - created=keyitem.attributes.created, - updated=keyitem.attributes.updated, - recovery_level=keyitem.attributes.recovery_level + enabled=keyitem.enabled, + not_before=keyitem.not_before, + expires=keyitem.expires_on, + created=keyitem.created_on, + updated=keyitem.updated_on, + recovery_level=keyitem.recovery_level + ) + ) + + +def delete_item_to_dict(bundle): + return dict( + tags=bundle.properties._tags, + kid=bundle.properties.id, + version=bundle.properties.version, + managed=bundle.properties.managed, + attributes=dict( + enabled=bundle.properties.enabled, + not_before=bundle.properties.not_before, + expires=bundle.properties.expires_on, + created=bundle.properties.created_on, + updated=bundle.properties.updated_on, + recovery_level=bundle.properties.recovery_level + + ) ) def deletedkeyitem_to_dict(keyitem): - item = keyitem_to_dict(keyitem) - item['recovery_id'] = keyitem.recovery_id, - item['scheduled_purge_date'] = keyitem.scheduled_purge_date, + item = delete_item_to_dict(keyitem) + item['recovery_id'] = keyitem.recovery_id + item['scheduled_purge_date'] = keyitem.scheduled_purge_date item['deleted_date'] = keyitem.deleted_date return item @@ -312,48 +372,8 @@ class AzureRMKeyVaultKeyInfo(AzureRMModuleBase): return self.results def get_keyvault_client(self): - kv_url = self.azure_auth._cloud_environment.suffixes.keyvault_dns.split('.', 1).pop() - # Don't use MSI credentials if the auth_source isn't set to MSI. The below will Always result in credentials when running on an Azure VM. - if self.module.params['auth_source'] == 'msi': - try: - self.log("Get KeyVaultClient from MSI") - credentials = MSIAuthentication(resource="https://{0}".format(kv_url)) - return KeyVaultClient(credentials) - except Exception: - self.log("Get KeyVaultClient from service principal") - elif (self.module.params['auth_source'] == 'cli' - or (self.module.params['auth_source'] == 'auto' - and self.credentials['client_id'] is None - and self.credentials['secret'] is None)): - try: - profile = get_cli_profile() - credentials, subscription_id, tenant = profile.get_login_credentials( - subscription_id=self.credentials['subscription_id'], resource="https://{0}".format(kv_url)) - return KeyVaultClient(credentials) - except Exception as exc: - self.log("Get KeyVaultClient from service principal") - # self.fail("Failed to load CLI profile {0}.".format(str(exc))) - - # Create KeyVault Client using KeyVault auth class and auth_callback - def auth_callback(server, resource, scope): - if self.credentials['client_id'] is None or self.credentials['secret'] is None: - self.fail('Please specify client_id, secret and tenant to access azure Key Vault.') - - tenant = self.credentials.get('tenant') - if not self.credentials['tenant']: - tenant = "common" - - authcredential = ServicePrincipalCredentials( - client_id=self.credentials['client_id'], - secret=self.credentials['secret'], - tenant=tenant, - cloud_environment=self._cloud_environment, - resource="https://{0}".format(kv_url)) - - token = authcredential.token - return token['token_type'], token['access_token'] - - return KeyVaultClient(KeyVaultAuthentication(auth_callback)) + + return KeyClient(vault_url=self.vault_uri, credential=self.azure_auth.azure_credential_track2) def get_key(self): ''' @@ -366,19 +386,20 @@ class AzureRMKeyVaultKeyInfo(AzureRMModuleBase): results = [] try: if self.version == 'current': - response = self._client.get_key(vault_base_url=self.vault_uri, - key_name=self.name, - key_version='') + response = self._client.get_key(name=self.name, + version=None) else: - response = self._client.get_key(vault_base_url=self.vault_uri, - key_name=self.name, - key_version=self.version) + response = self._client.get_key(name=self.name, + version=self.version) - if response and self.has_tags(response.tags, self.tags): - self.log("Response : {0}".format(response)) - results.append(keybundle_to_dict(response)) + if response: + response = keybundle_to_dict(response) + if self.has_tags(response['tags'], self.tags): + self.log("Response : {0}".format(response)) + results.append(response) except Exception as e: + self.fail(e) self.log("Did not find the key vault key {0}: {1}".format(self.name, str(e))) return results @@ -392,14 +413,14 @@ class AzureRMKeyVaultKeyInfo(AzureRMModuleBase): results = [] try: - response = self._client.get_key_versions(vault_base_url=self.vault_uri, - key_name=self.name) + response = self._client.list_properties_of_key_versions(name=self.name) self.log("Response : {0}".format(response)) if response: for item in response: - if self.has_tags(item.tags, self.tags): - results.append(keyitem_to_dict(item)) + item = keyitem_to_dict(item) + if self.has_tags(item['tags'], self.tags): + results.append(item) except Exception as e: self.log("Did not find key versions {0} : {1}.".format(self.name, str(e))) return results @@ -414,13 +435,14 @@ class AzureRMKeyVaultKeyInfo(AzureRMModuleBase): results = [] try: - response = self._client.get_keys(vault_base_url=self.vault_uri) + response = self._client.list_properties_of_keys() self.log("Response : {0}".format(response)) if response: for item in response: - if self.has_tags(item.tags, self.tags): - results.append(keyitem_to_dict(item)) + item = keyitem_to_dict(item) + if self.has_tags(item['tags'], self.tags): + results.append(item) except Exception as e: self.log("Did not find key vault in current subscription {0}.".format(str(e))) return results @@ -435,12 +457,13 @@ class AzureRMKeyVaultKeyInfo(AzureRMModuleBase): results = [] try: - response = self._client.get_deleted_key(vault_base_url=self.vault_uri, - key_name=self.name) + response = self._client.get_deleted_key(name=self.name) - if response and self.has_tags(response.tags, self.tags): - self.log("Response : {0}".format(response)) - results.append(deletedkeybundle_to_dict(response)) + if response: + response = deletedkeybundle_to_dict(response) + if self.has_tags(response['tags'], self.tags): + self.log("Response : {0}".format(response)) + results.append(response) except Exception as e: self.log("Did not find the key vault key {0}: {1}".format(self.name, str(e))) @@ -456,13 +479,14 @@ class AzureRMKeyVaultKeyInfo(AzureRMModuleBase): results = [] try: - response = self._client.get_deleted_keys(vault_base_url=self.vault_uri) + response = self._client.list_deleted_keys() self.log("Response : {0}".format(response)) if response: for item in response: - if self.has_tags(item.tags, self.tags): - results.append(deletedkeyitem_to_dict(item)) + item = deletedkeyitem_to_dict(item) + if self.has_tags(item['tags'], self.tags): + results.append(item) except Exception as e: self.log("Did not find key vault in current subscription {0}.".format(str(e))) return results diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultsecret.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultsecret.py index 0a5288abb..98a5e0e78 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultsecret.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultsecret.py @@ -18,9 +18,10 @@ description: - Such as authentication keys, storage account keys, data encryption keys, .PFX files, and passwords. options: keyvault_uri: - description: - - URI of the keyvault endpoint. - required: true + description: + - URI of the keyvault endpoint. + required: true + type: str content_type: description: - Type of the secret value such as a password. @@ -29,9 +30,11 @@ options: description: - Name of the keyvault secret. required: true + type: str secret_value: description: - Secret to be secured by keyvault. + type: str secret_expiry: description: - Optional expiry datetime for secret @@ -43,6 +46,7 @@ options: state: description: - Assert the state of the subnet. Use C(present) to create or update a secret and C(absent) to delete a secret . + type: str default: present choices: - absent @@ -58,20 +62,20 @@ author: ''' EXAMPLES = ''' - - name: Create a secret - azure_rm_keyvaultsecret: - secret_name: MySecret - secret_value: My_Pass_Sec - keyvault_uri: https://contoso.vault.azure.net/ - tags: - testing: testing - delete: never - - - name: Delete a secret - azure_rm_keyvaultsecret: - secret_name: MySecret - keyvault_uri: https://contoso.vault.azure.net/ - state: absent +- name: Create a secret + azure_rm_keyvaultsecret: + secret_name: MySecret + secret_value: My_Pass_Sec + keyvault_uri: https://contoso.vault.azure.net/ + tags: + testing: testing + delete: never + +- name: Delete a secret + azure_rm_keyvaultsecret: + secret_name: MySecret + keyvault_uri: https://contoso.vault.azure.net/ + state: absent ''' RETURN = ''' @@ -91,12 +95,8 @@ state: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: - from azure.keyvault import KeyVaultClient, KeyVaultAuthentication, KeyVaultId - from azure.common.credentials import ServicePrincipalCredentials, get_cli_profile - from msrestazure.azure_active_directory import MSIAuthentication + from azure.keyvault.secrets import SecretClient import dateutil.parser - from azure.keyvault.models import SecretAttributes - # from azure.keyvault.models.secret_attributes import SecretAttributes except ImportError: # This is handled in azure_rm_common pass @@ -162,7 +162,7 @@ class AzureRMKeyVaultSecret(AzureRMModuleBase): elif self.secret_value and results['secret_value'] != self.secret_value: changed = True - except Exception: + except Exception as ec: # Secret doesn't exist if self.state == 'present': changed = True @@ -198,69 +198,32 @@ class AzureRMKeyVaultSecret(AzureRMModuleBase): return self.results def get_keyvault_client(self): - kv_url = self.azure_auth._cloud_environment.suffixes.keyvault_dns.split('.', 1).pop() - # Don't use MSI credentials if the auth_source isn't set to MSI. The below will Always result in credentials when running on an Azure VM. - if self.module.params['auth_source'] == 'msi': - try: - self.log("Get KeyVaultClient from MSI") - credentials = MSIAuthentication(resource="https://{0}".format(kv_url)) - return KeyVaultClient(credentials) - except Exception: - self.log("Get KeyVaultClient from service principal") - elif (self.module.params['auth_source'] == 'cli' - or (self.module.params['auth_source'] == 'auto' - and self.credentials['client_id'] is None - and self.credentials['secret'] is None)): - try: - profile = get_cli_profile() - credentials, subscription_id, tenant = profile.get_login_credentials( - subscription_id=self.credentials['subscription_id'], resource="https://{0}".format(kv_url)) - return KeyVaultClient(credentials) - except Exception as exc: - self.log("Get KeyVaultClient from service principal") - # self.fail("Failed to load CLI profile {0}.".format(str(exc))) - - # Create KeyVault Client using KeyVault auth class and auth_callback - def auth_callback(server, resource, scope): - if self.credentials['client_id'] is None or self.credentials['secret'] is None: - self.fail('Please specify client_id, secret and tenant to access azure Key Vault.') - - tenant = self.credentials.get('tenant') - if not self.credentials['tenant']: - tenant = "common" - - authcredential = ServicePrincipalCredentials( - client_id=self.credentials['client_id'], - secret=self.credentials['secret'], - tenant=tenant, - cloud_environment=self._cloud_environment, - resource="https://{0}".format(kv_url)) - - token = authcredential.token - return token['token_type'], token['access_token'] - - return KeyVaultClient(KeyVaultAuthentication(auth_callback)) + + return SecretClient(vault_url=self.keyvault_uri, credential=self.azure_auth.azure_credential_track2) def get_secret(self, name, version=''): ''' Gets an existing secret ''' - secret_bundle = self.client.get_secret(self.keyvault_uri, name, version) + secret_bundle = self.client.get_secret(name=name, version=version) + if secret_bundle: - secret_id = KeyVaultId.parse_secret_id(secret_bundle.id) - return dict(secret_id=secret_id.id, secret_value=secret_bundle.value) + return dict(secret_id=secret_bundle.id, secret_value=secret_bundle.value) return None def create_update_secret(self, name, secret, tags, content_type, valid_from, expiry): ''' Creates/Updates a secret ''' - secret_attributes = SecretAttributes(expires=expiry, not_before=valid_from) - secret_bundle = self.client.set_secret(self.keyvault_uri, name, secret, tags=tags, content_type=content_type, secret_attributes=secret_attributes) - secret_id = KeyVaultId.parse_secret_id(secret_bundle.id) - return secret_id.id + secret_bundle = self.client.set_secret(name=name, + value=secret, + tags=tags, + content_type=content_type, + expires_on=expiry, + not_before=valid_from) + return secret_bundle._properties._id def delete_secret(self, name): ''' Deletes a secret ''' - deleted_secret = self.client.delete_secret(self.keyvault_uri, name) - secret_id = KeyVaultId.parse_secret_id(deleted_secret.id) - return secret_id.id + deleted_secret = self.client.begin_delete_secret(name) + result = self.get_poller_result(deleted_secret) + return result.properties._id def main(): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultsecret_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultsecret_info.py index a785b8ce7..b612dce36 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultsecret_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultsecret_info.py @@ -53,31 +53,31 @@ author: ''' EXAMPLES = ''' - - name: Get latest version of specific secret - azure_rm_keyvaultsecret_info: - vault_uri: "https://myVault.vault.azure.net" - name: mySecret - - - name: List all versions of specific secret - azure_rm_keyvaultsecret_info: - vault_uri: "https://myVault.vault.azure.net" - name: mySecret - version: all - - - name: List specific version of specific secret - azure_rm_keyvaultsecret_info: - vault_uri: "https://myVault.vault.azure.net" - name: mySecret - version: fd2682392a504455b79c90dd04a1bf46 - - - name: List all secrets in specific key vault - azure_rm_keyvaultsecret_info: - vault_uri: "https://myVault.vault.azure.net" - - - name: List deleted secrets in specific key vault - azure_rm_keyvaultsecret_info: - vault_uri: "https://myVault.vault.azure.net" - show_deleted_secret: True +- name: Get latest version of specific secret + azure_rm_keyvaultsecret_info: + vault_uri: "https://myVault.vault.azure.net" + name: mySecret + +- name: List all versions of specific secret + azure_rm_keyvaultsecret_info: + vault_uri: "https://myVault.vault.azure.net" + name: mySecret + version: all + +- name: List specific version of specific secret + azure_rm_keyvaultsecret_info: + vault_uri: "https://myVault.vault.azure.net" + name: mySecret + version: fd2682392a504455b79c90dd04a1bf46 + +- name: List all secrets in specific key vault + azure_rm_keyvaultsecret_info: + vault_uri: "https://myVault.vault.azure.net" + +- name: List deleted secrets in specific key vault + azure_rm_keyvaultsecret_info: + vault_uri: "https://myVault.vault.azure.net" + show_deleted_secret: true ''' RETURN = ''' @@ -162,55 +162,68 @@ secrets: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: - from azure.keyvault import KeyVaultClient, KeyVaultId, KeyVaultAuthentication - from azure.common.credentials import ServicePrincipalCredentials, get_cli_profile - from msrestazure.azure_active_directory import MSIAuthentication + from azure.keyvault.secrets import SecretClient except ImportError: # This is handled in azure_rm_common pass def secretbundle_to_dict(bundle): + return dict(tags=bundle._properties._tags, + attributes=dict( + enabled=bundle._properties._attributes.enabled, + not_before=bundle._properties._attributes.not_before, + expires=bundle._properties._attributes.expires, + created=bundle._properties._attributes.created, + updated=bundle._properties._attributes.updated, + recovery_level=bundle._properties._attributes.recovery_level), + sid=bundle._properties._id, + version=bundle._properties.version, + content_type=bundle._properties._content_type, + secret=bundle._value) + + +def deleted_bundle_to_dict(bundle): return dict(tags=bundle.tags, attributes=dict( - enabled=bundle.attributes.enabled, - not_before=bundle.attributes.not_before, - expires=bundle.attributes.expires, - created=bundle.attributes.created, - updated=bundle.attributes.updated, - recovery_level=bundle.attributes.recovery_level), + enabled=bundle.enabled, + not_before=bundle.not_before, + expires=bundle.expires_on, + created=bundle.created_on, + updated=bundle.updated_on, + recovery_level=bundle.recovery_level), sid=bundle.id, - version=KeyVaultId.parse_secret_id(bundle.id).version, + version=bundle.key_id, content_type=bundle.content_type, - secret=bundle.value) + secret=bundle.version) def deletedsecretbundle_to_dict(bundle): - secretbundle = secretbundle_to_dict(bundle) - secretbundle['recovery_id'] = bundle.recovery_id, - secretbundle['scheduled_purge_date'] = bundle.scheduled_purge_date, - secretbundle['deleted_date'] = bundle.deleted_date + secretbundle = deleted_bundle_to_dict(bundle.properties) + secretbundle['recovery_id'] = bundle._recovery_id + secretbundle['scheduled_purge_date'] = bundle._scheduled_purge_date + secretbundle['deleted_date'] = bundle._deleted_date return secretbundle def secretitem_to_dict(secretitem): - return dict(sid=secretitem.id, - version=KeyVaultId.parse_secret_id(secretitem.id).version, - tags=secretitem.tags, + return dict(sid=secretitem._id, + version=secretitem.version, + tags=secretitem._tags, attributes=dict( - enabled=secretitem.attributes.enabled, - not_before=secretitem.attributes.not_before, - expires=secretitem.attributes.expires, - created=secretitem.attributes.created, - updated=secretitem.attributes.updated, - recovery_level=secretitem.attributes.recovery_level)) + enabled=secretitem._attributes.enabled, + not_before=secretitem._attributes.not_before, + expires=secretitem._attributes.expires, + created=secretitem._attributes.created, + updated=secretitem._attributes.updated, + recovery_level=secretitem._attributes.recovery_level)) def deletedsecretitem_to_dict(secretitem): - item = secretitem_to_dict(secretitem) - item['recovery_id'] = secretitem.recovery_id, - item['scheduled_purge_date'] = secretitem.scheduled_purge_date, - item['deleted_date'] = secretitem.deleted_date + item = secretitem_to_dict(secretitem.properties) + item['recovery_id'] = secretitem._recovery_id + item['scheduled_purge_date'] = secretitem._scheduled_purge_date + item['deleted_date'] = secretitem._deleted_date return item @@ -265,52 +278,8 @@ class AzureRMKeyVaultSecretInfo(AzureRMModuleBase): return self.results def get_keyvault_client(self): - kv_url = self.azure_auth._cloud_environment.suffixes.keyvault_dns.split('.', 1).pop() - # Don't use MSI credentials if the auth_source isn't set to MSI. The below will Always result in credentials when running on an Azure VM. - if self.module.params['auth_source'] == 'msi': - try: - self.log("Get KeyVaultClient from MSI") - resource = self.azure_auth._cloud_environment.suffixes.keyvault_dns.split('.', 1).pop() - credentials = MSIAuthentication(resource="https://{0}".format(resource)) - return KeyVaultClient(credentials) - except Exception: - self.log("Get KeyVaultClient from service principal") - elif (self.module.params['auth_source'] == 'cli' - or (self.module.params['auth_source'] == 'auto' - and self.credentials['client_id'] is None - and self.credentials['secret'] is None)): - try: - profile = get_cli_profile() - credentials, subscription_id, tenant = profile.get_login_credentials( - subscription_id=self.credentials['subscription_id'], resource="https://{0}".format(kv_url)) - return KeyVaultClient(credentials) - except Exception as exc: - self.log("Get KeyVaultClient from service principal") - # self.fail("Failed to load CLI profile {0}.".format(str(exc))) - - # Create KeyVault Client using KeyVault auth class and auth_callback - def auth_callback(server, resource, scope): - if self.credentials['client_id'] is None or self.credentials[ - 'secret'] is None: - self.fail( - 'Please specify client_id, secret and tenant to access azure Key Vault.' - ) - - tenant = self.credentials.get('tenant') - if not self.credentials['tenant']: - tenant = "common" - - authcredential = ServicePrincipalCredentials( - client_id=self.credentials['client_id'], - secret=self.credentials['secret'], - tenant=tenant, - cloud_environment=self._cloud_environment, - resource="https://{0}".format(kv_url)) - - token = authcredential.token - return token['token_type'], token['access_token'] - - return KeyVaultClient(KeyVaultAuthentication(auth_callback)) + + return SecretClient(vault_url=self.vault_uri, credential=self.azure_auth.azure_credential_track2) def get_secret(self): ''' @@ -323,19 +292,15 @@ class AzureRMKeyVaultSecretInfo(AzureRMModuleBase): results = [] try: if self.version == 'current': - response = self._client.get_secret( - vault_base_url=self.vault_uri, - secret_name=self.name, - secret_version='') + response = self._client.get_secret(name=self.name, version='') else: - response = self._client.get_secret( - vault_base_url=self.vault_uri, - secret_name=self.name, - secret_version=self.version) + response = self._client.get_secret(name=self.name, version=self.version) - if response and self.has_tags(response.tags, self.tags): - self.log("Response : {0}".format(response)) - results.append(secretbundle_to_dict(response)) + if response: + response = secretbundle_to_dict(response) + if self.has_tags(response['tags'], self.tags): + self.log("Response : {0}".format(response)) + results.append(response) except Exception as e: self.log("Did not find the key vault secret {0}: {1}".format( @@ -352,14 +317,14 @@ class AzureRMKeyVaultSecretInfo(AzureRMModuleBase): results = [] try: - response = self._client.get_secret_versions( - vault_base_url=self.vault_uri, secret_name=self.name) + response = self._client.list_properties_of_secret_versions(name=self.name) self.log("Response : {0}".format(response)) if response: for item in response: - if self.has_tags(item.tags, self.tags): - results.append(secretitem_to_dict(item)) + item = secretitem_to_dict(item) + if self.has_tags(item['tags'], self.tags): + results.append(item) except Exception as e: self.log("Did not find secret versions {0} : {1}.".format( self.name, str(e))) @@ -375,13 +340,14 @@ class AzureRMKeyVaultSecretInfo(AzureRMModuleBase): results = [] try: - response = self._client.get_secrets(vault_base_url=self.vault_uri) + response = self._client.list_properties_of_secrets() self.log("Response : {0}".format(response)) if response: for item in response: - if self.has_tags(item.tags, self.tags): - results.append(secretitem_to_dict(item)) + item = secretitem_to_dict(item) + if self.has_tags(item['tags'], self.tags): + results.append(item) except Exception as e: self.log( "Did not find key vault in current subscription {0}.".format( @@ -398,12 +364,13 @@ class AzureRMKeyVaultSecretInfo(AzureRMModuleBase): results = [] try: - response = self._client.get_deleted_secret( - vault_base_url=self.vault_uri, secret_name=self.name) + response = self._client.get_deleted_secret(name=self.name) - if response and self.has_tags(response.tags, self.tags): - self.log("Response : {0}".format(response)) - results.append(deletedsecretbundle_to_dict(response)) + if response: + response = deletedsecretbundle_to_dict(response) + if self.has_tags(response['tags'], self.tags): + self.log("Response : {0}".format(response)) + results.append(response) except Exception as e: self.log("Did not find the key vault secret {0}: {1}".format( @@ -420,14 +387,14 @@ class AzureRMKeyVaultSecretInfo(AzureRMModuleBase): results = [] try: - response = self._client.get_deleted_secrets( - vault_base_url=self.vault_uri) + response = self._client.list_deleted_secrets() self.log("Response : {0}".format(response)) if response: for item in response: - if self.has_tags(item.tags, self.tags): - results.append(deletedsecretitem_to_dict(item)) + item = deletedsecretitem_to_dict(item) + if self.has_tags(item['tags'], self.tags): + results.append(item) except Exception as e: self.log( "Did not find key vault in current subscription {0}.".format( diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_loadbalancer.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_loadbalancer.py index 86c4335f8..2c473778c 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_loadbalancer.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_loadbalancer.py @@ -24,43 +24,54 @@ options: description: - Name of a resource group where the load balancer exists or will be created. required: true + type: str name: description: - Name of the load balancer. required: true + type: str state: description: - Assert the state of the load balancer. Use C(present) to create/update a load balancer, or C(absent) to delete one. default: present + type: str choices: - absent - present location: description: - Valid Azure location. Defaults to location of the resource group. + type: str sku: description: - The load balancer SKU. + type: str choices: - Basic - Standard frontend_ip_configurations: description: - List of frontend IPs to be used. + type: list + elements: dict suboptions: name: description: - Name of the frontend ip configuration. + type: str required: True public_ip_address: description: - Name of an existing public IP address object in the current resource group to associate with the security group. + type: str private_ip_address: description: - The reference of the Public IP resource. + type: str private_ip_allocation_method: description: - The Private IP allocation method. + type: str choices: - Static - Dynamic @@ -68,6 +79,7 @@ options: description: - The reference of the subnet resource. - Should be an existing subnet's resource id. + type: str zones: description: - list of availability zones denoting the IP allocated for the resource needs to come from. @@ -77,28 +89,36 @@ options: backend_address_pools: description: - List of backend address pools. + type: list + elements: dict suboptions: name: description: - Name of the backend address pool. required: True + type: str probes: description: - List of probe definitions used to check endpoint health. + type: list + elements: dict suboptions: name: description: - Name of the probe. + type: str required: True port: description: - Probe port for communicating the probe. Possible values range from 1 to 65535, inclusive. + type: int required: True protocol: description: - The protocol of the end point to be probed. - If C(Tcp) is specified, a received ACK is required for the probe to be successful. - If C(Http) or C(Https) is specified, a 200 OK response from the specified URL is required for the probe to be successful. + type: str choices: - Tcp - Http @@ -108,18 +128,21 @@ options: - The interval, in seconds, for how frequently to probe the endpoint for health status. - Slightly less than half the allocated timeout period, which allows two full probes before taking the instance out of rotation. - The default value is C(15), the minimum value is C(5). + type: int default: 15 fail_count: description: - The number of probes where if no response, will result in stopping further traffic from being delivered to the endpoint. - This values allows endpoints to be taken out of rotation faster or slower than the typical times used in Azure. default: 3 + type: int aliases: - number_of_probes request_path: description: - The URI used for requesting health status from the VM. - Path is required if I(protocol=Http) or I(protocol=Https). Otherwise, it is not allowed. + type: str inbound_nat_pools: description: - Defines an external port range for inbound NAT to a single backend port on NICs associated with a load balancer. @@ -128,18 +151,23 @@ options: - Inbound NAT pools are referenced from virtual machine scale sets. - NICs that are associated with individual virtual machines cannot reference an inbound NAT pool. - They have to reference individual inbound NAT rules. + type: list + elements: dict suboptions: name: description: - Name of the inbound NAT pool. + type: str required: True frontend_ip_configuration_name: description: - A reference to frontend IP addresses. required: True + type: str protocol: description: - IP protocol for the NAT pool. + type: str choices: - Tcp - Udp @@ -148,39 +176,50 @@ options: description: - The first port in the range of external ports that will be used to provide inbound NAT to NICs associated with the load balancer. - Acceptable values range between 1 and 65534. + type: int required: True frontend_port_range_end: description: - The last port in the range of external ports that will be used to provide inbound NAT to NICs associated with the load balancer. - Acceptable values range between 1 and 65535. + type: int required: True backend_port: description: - The port used for internal connections on the endpoint. - Acceptable values are between 1 and 65535. + type: int + required: true load_balancing_rules: description: - Object collection representing the load balancing rules Gets the provisioning. + type: list + elements: dict suboptions: name: description: - Name of the load balancing rule. + type: str required: True frontend_ip_configuration: description: - A reference to frontend IP addresses. + type: str required: True backend_address_pool: description: - A reference to a pool of DIPs. Inbound traffic is randomly load balanced across IPs in the backend IPs. required: True + type: str probe: description: - The name of the load balancer probe this rule should use for health checks. required: True + type: str protocol: description: - IP protocol for the load balancing rule. + type: str choices: - Tcp - Udp @@ -188,6 +227,7 @@ options: load_distribution: description: - The session persistence policy for this rule; C(Default) is no persistence. + type: str choices: - Default - SourceIP @@ -199,26 +239,34 @@ options: - Frontend port numbers must be unique across all rules within the load balancer. - Acceptable values are between 0 and 65534. - Note that value 0 enables "Any Port". + type: int + required: true backend_port: description: - The port used for internal connections on the endpoint. - Acceptable values are between 0 and 65535. - Note that value 0 enables "Any Port". + type: int idle_timeout: description: - The timeout for the TCP idle connection. - The value can be set between 4 and 30 minutes. - The default value is C(4) minutes. - This element is only used when the protocol is set to TCP. + type: int + default: 4 enable_floating_ip: description: - Configures a virtual machine's endpoint for the floating IP capability required to configure a SQL AlwaysOn Availability Group. + type: bool disable_outbound_snat: description: - Configure outbound source network address translation (SNAT). - The default behavior when omitted is equivalent to I(disable_outbound_snat=True). - True is equivalent to "(Recommended) Use outbound rules to provide backend pool members access to the internet" in portal. - False is equivalent to "Use default outbound access" in portal. + type: bool + default: False inbound_nat_rules: description: - Collection of inbound NAT Rules used by a load balancer. @@ -226,18 +274,23 @@ options: - Inbound NAT pools are referenced from virtual machine scale sets. - NICs that are associated with individual virtual machines cannot reference an Inbound NAT pool. - They have to reference individual inbound NAT rules. + type: list + elements: dict suboptions: name: description: - name of the inbound nat rule. + type: str required: True frontend_ip_configuration: description: - A reference to frontend IP addresses. + type: str required: True protocol: description: - IP protocol for the inbound nat rule. + type: str choices: - Tcp - Udp @@ -248,30 +301,38 @@ options: - Frontend port numbers must be unique across all rules within the load balancer. - Acceptable values are between 0 and 65534. - Note that value 0 enables "Any Port". + type: int + required: True backend_port: description: - The port used for internal connections on the endpoint. - Acceptable values are between 0 and 65535. - Note that value 0 enables "Any Port". + type: int + required: true idle_timeout: description: - The timeout for the TCP idle connection. - The value can be set between 4 and 30 minutes. - The default value is C(4) minutes. - This element is only used when I(protocol=Tcp). + type: int enable_floating_ip: description: - Configures a virtual machine's endpoint for the floating IP capability required to configure a SQL AlwaysOn Availability Group. - This setting is required when using the SQL AlwaysOn Availability Groups in SQL server. - This setting can't be changed after you create the endpoint. + type: bool enable_tcp_reset: description: - Receive bidirectional TCP Reset on TCP flow idle timeout or unexpected connection termination. - This element is only used when I(protocol=Tcp). + type: bool public_ip_address_name: description: - (deprecated) Name of an existing public IP address object to associate with the security group. - This option has been deprecated, and will be removed in 2.9. Use I(frontend_ip_configurations) instead. + type: str aliases: - public_ip_address - public_ip_name @@ -280,10 +341,12 @@ options: description: - (deprecated) The port that the health probe will use. - This option has been deprecated, and will be removed in 2.9. Use I(probes) instead. + type: int probe_protocol: description: - (deprecated) The protocol to use for the health probe. - This option has been deprecated, and will be removed in 2.9. Use I(probes) instead. + type: str choices: - Tcp - Http @@ -292,20 +355,24 @@ options: description: - (deprecated) Time (in seconds) between endpoint health probes. - This option has been deprecated, and will be removed in 2.9. Use I(probes) instead. + type: int default: 15 probe_fail_count: description: - (deprecated) The amount of probe failures for the load balancer to make a health determination. - This option has been deprecated, and will be removed in 2.9. Use I(probes) instead. default: 3 + type: int probe_request_path: description: - (deprecated) The URL that an HTTP probe or HTTPS probe will use (only relevant if I(probe_protocol=Http) or I(probe_protocol=Https)). - This option has been deprecated, and will be removed in 2.9. Use I(probes) instead. + type: str protocol: description: - (deprecated) The protocol (TCP or UDP) that the load balancer will use. - This option has been deprecated, and will be removed in 2.9. Use I(load_balancing_rules) instead. + type: str choices: - Tcp - Udp @@ -313,6 +380,7 @@ options: description: - (deprecated) The type of load distribution that the load balancer will employ. - This option has been deprecated, and will be removed in 2.9. Use I(load_balancing_rules) instead. + type: str choices: - Default - SourceIP @@ -321,31 +389,38 @@ options: description: - (deprecated) Frontend port that will be exposed for the load balancer. - This option has been deprecated, and will be removed in 2.9. Use I(load_balancing_rules) instead. + type: int backend_port: description: - (deprecated) Backend port that will be exposed for the load balancer. - This option has been deprecated, and will be removed in 2.9. Use I(load_balancing_rules) instead. + type: int idle_timeout: description: - (deprecated) Timeout for TCP idle connection in minutes. - This option has been deprecated, and will be removed in 2.9. Use I(load_balancing_rules) instead. + type: int default: 4 natpool_frontend_port_start: description: - (deprecated) Start of the port range for a NAT pool. - This option has been deprecated, and will be removed in 2.9. Use I(inbound_nat_pools) instead. + type: int natpool_frontend_port_end: description: - (deprecated) End of the port range for a NAT pool. - This option has been deprecated, and will be removed in 2.9. Use I(inbound_nat_pools) instead. + type: int natpool_backend_port: description: - (deprecated) Backend port used by the NAT pool. - This option has been deprecated, and will be removed in 2.9. Use I(inbound_nat_pools) instead. + type: int natpool_protocol: description: - (deprecated) The protocol for the NAT pool. - This option has been deprecated, and will be removed in 2.9. Use I(inbound_nat_pools) instead. + type: str extends_documentation_fragment: - azure.azcollection.azure - azure.azcollection.azure_tags @@ -403,12 +478,9 @@ changed: type: bool ''' -import random from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, format_resource_id from ansible.module_utils._text import to_native try: - from msrestazure.tools import parse_resource_id - from msrestazure.azure_exceptions import CloudError from azure.core.exceptions import ResourceNotFoundError except ImportError: # This is handled in azure_rm_common @@ -427,7 +499,8 @@ frontend_ip_configuration_spec = dict( type='str' ), private_ip_allocation_method=dict( - type='str' + type='str', + choices=['Static', 'Dynamic'] ), subnet=dict( type='str' @@ -578,7 +651,7 @@ load_balancing_rule_spec = dict( ), disable_outbound_snat=dict( type='bool', - default=None + default=False ), ) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_loadbalancer_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_loadbalancer_info.py index 130e12d5c..45f7df094 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_loadbalancer_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_loadbalancer_info.py @@ -43,22 +43,22 @@ author: ''' EXAMPLES = ''' - - name: Get facts for one load balancer - azure_rm_loadbalancer_info: - name: Testing - resource_group: myResourceGroup - - - name: Get facts for all load balancers - azure_rm_loadbalancer_info: - - - name: Get facts for all load balancers in a specific resource group - azure_rm_loadbalancer_info: - resource_group: myResourceGroup - - - name: Get facts by tags - azure_rm_loadbalancer_info: - tags: - - testing +- name: Get facts for one load balancer + azure_rm_loadbalancer_info: + name: Testing + resource_group: myResourceGroup + +- name: Get facts for all load balancers + azure_rm_loadbalancer_info: + +- name: Get facts for all load balancers in a specific resource group + azure_rm_loadbalancer_info: + resource_group: myResourceGroup + +- name: Get facts by tags + azure_rm_loadbalancer_info: + tags: + - testing ''' RETURN = ''' @@ -116,7 +116,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError - from azure.common import AzureHttpError except Exception: # handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_lock_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_lock_info.py index ef9f3e303..39abbf3b7 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_lock_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_lock_info.py @@ -20,7 +20,6 @@ options: description: - Name of the lock. type: str - required: true managed_resource_id: description: - ID of the resource where need to manage the lock. @@ -115,7 +114,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase - from msrestazure.azure_exceptions import CloudError except ImportError: # This is handled in azure_rm_common pass @@ -160,7 +158,7 @@ class AzureRMLockInfo(AzureRMModuleBase): for key in self.module_arg_spec.keys(): setattr(self, key, kwargs[key]) - self._mgmt_client = self.get_mgmt_svc_client(GenericRestClient, base_url=self._cloud_environment.endpoints.resource_manager) + self._mgmt_client = self.get_mgmt_svc_client(GenericRestClient, is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) changed = False # construct scope id scope = self.get_scope() @@ -195,8 +193,8 @@ class AzureRMLockInfo(AzureRMModuleBase): expected_status_codes=[200], polling_timeout=None, polling_interval=None) - return json.loads(resp.text) - except CloudError as exc: + return json.loads(resp.body()) + except Exception as exc: self.fail('Error when finding locks {0}: {1}'.format(url, exc.message)) def get_scope(self): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_loganalyticsworkspace.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_loganalyticsworkspace.py index 7e8acf260..b323d9292 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_loganalyticsworkspace.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_loganalyticsworkspace.py @@ -20,23 +20,28 @@ options: description: - Name of resource group. required: true + type: str name: description: - Name of the workspace. required: true + type: str state: description: - Assert the state of the image. Use C(present) to create or update a image and C(absent) to delete an image. default: present + type: str choices: - absent - present location: description: - Resource location. + type: str sku: description: - The SKU of the workspace. + type: str choices: - free - standard @@ -51,6 +56,7 @@ options: - The workspace data retention in days. - -1 means Unlimited retention for I(sku=unlimited). - 730 days is the maximum allowed for all other SKUs. + type: int intelligence_packs: description: - Manage intelligence packs possible for this workspace. @@ -77,7 +83,7 @@ EXAMPLES = ''' resource_group: myResourceGroup name: myLogAnalyticsWorkspace intelligence_pack: - Backup: true + Backup: true ''' RETURN = ''' @@ -154,8 +160,7 @@ usages: from ansible.module_utils.common.dict_transformations import _snake_to_camel, _camel_to_snake try: - from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, format_resource_id - from msrestazure.tools import parse_resource_id + from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError except ImportError: # This is handled in azure_rm_common diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_loganalyticsworkspace_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_loganalyticsworkspace_info.py index 4861954da..03a55bedc 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_loganalyticsworkspace_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_loganalyticsworkspace_info.py @@ -20,9 +20,11 @@ options: description: - Name of resource group. required: True + type: str name: description: - Name of the workspace. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -32,18 +34,22 @@ options: description: - Show the intelligence packs for a workspace. - Note this will cost one more network overhead for each workspace, expected slow response. + type: bool show_management_groups: description: - Show the management groups for a workspace. - Note this will cost one more network overhead for each workspace, expected slow response. + type: bool show_shared_keys: description: - Show the shared keys for a workspace. - Note this will cost one more network overhead for each workspace, expected slow response. + type: bool show_usages: description: - Show the list of usages for a workspace. - Note this will cost one more network overhead for each workspace, expected slow response. + type: bool extends_documentation_fragment: - azure.azcollection.azure @@ -134,11 +140,10 @@ usages: } ''' # NOQA -from ansible.module_utils.common.dict_transformations import _snake_to_camel, _camel_to_snake +from ansible.module_utils.common.dict_transformations import _camel_to_snake try: - from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, format_resource_id - from msrestazure.tools import parse_resource_id + from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError except ImportError: # This is handled in azure_rm_common diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_manageddisk.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_manageddisk.py index e11965381..2b27fbbff 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_manageddisk.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_manageddisk.py @@ -27,20 +27,24 @@ options: description: - Name of a resource group where the managed disk exists or will be created. required: true + type: str name: description: - Name of the managed disk. required: true + type: str state: description: - Assert the state of the managed disk. Use C(present) to create or update a managed disk and C(absent) to delete a managed disk. default: present + type: str choices: - absent - present location: description: - Valid Azure location. Defaults to location of the resource group. + type: str storage_account_type: description: - Type of storage for the managed disk. @@ -52,6 +56,7 @@ options: - C(Premium_ZRS) is for Premium SSD Zone-redundant. - C(UltraSSD_LRS) (added in 2.8) is for Ultra SSD, which is only available on select instance types. - See U(https://docs.microsoft.com/en-us/azure/virtual-machines/windows/disks-types) for more information about disk types. + type: str choices: - Standard_LRS - StandardSSD_LRS @@ -62,6 +67,7 @@ options: create_option: description: - C(import) from a VHD file in I(source_uri) and C(copy) from previous managed disk I(source_uri). + type: str choices: - empty - import @@ -74,6 +80,7 @@ options: source_uri: description: - URI to a valid VHD file to be used or the resource ID of the managed disk to copy. + type: str aliases: - source_resource_uri os_type: @@ -83,6 +90,7 @@ options: - If omitted during creation, no value is set. - If omitted during an update, no change is made. - Once set, this value cannot be cleared. + type: str choices: - linux - windows @@ -90,11 +98,13 @@ options: description: - Size in GB of the managed disk to be created. - If I(create_option=copy) then the value must be greater than or equal to the source's size. + type: int managed_by: description: - Name of an existing virtual machine with which the disk is or will be associated, this VM should be in the same resource group. - To detach a disk from a vm, explicitly set to ''. - If this option is unset, the value will not be changed. + type: str managed_by_extended: description: - List of name and resource group of the VMs that have the disk attached. @@ -119,6 +129,7 @@ options: description: - Disk caching policy controlled by VM. Will be used when attached to the VM defined by C(managed_by). - If this option is different from the current caching policy, the managed disk will be deattached and attached with current caching option again. + type: str choices: - '' - read_only @@ -127,6 +138,7 @@ options: description: - The Azure managed disk's zone. - Allowed values are C(1), C(2), C(3) and C(''). + type: str choices: - '1' - '2' @@ -146,61 +158,61 @@ author: ''' EXAMPLES = ''' - - name: Create managed disk - azure_rm_manageddisk: - name: mymanageddisk - location: eastus - resource_group: myResourceGroup - disk_size_gb: 4 - - - name: Create managed operating system disk from page blob - azure_rm_manageddisk: - name: mymanageddisk - location: eastus2 - resource_group: myResourceGroup - create_option: import - source_uri: https://storageaccountname.blob.core.windows.net/containername/blob-name.vhd - storage_account_id: /subscriptions/<uuid>/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/storageaccountname - os_type: windows - storage_account_type: Premium_LRS - - - name: Mount the managed disk to VM - azure_rm_manageddisk: - name: mymanageddisk - location: eastus - resource_group: myResourceGroup - disk_size_gb: 4 - managed_by: testvm001 - attach_caching: read_only - - - name: Mount the managed disk to multiple VMs - azure_rm_manageddisk: - resource_group: myResourceGroup - name: freddisk04 - max_shares: 4 - disk_size_gb: 1024 - storage_account_type: Premium_LRS - managed_by_extended: - - resource_group: myResourceGroup01 - name: testVM01 - - resource_group: myResourceGroup02 - name: testVM02 - zone: 1 - - - name: Unmount the managed disk to VM - azure_rm_manageddisk: - name: mymanageddisk - location: eastus - resource_group: myResourceGroup - managed_by: '' - disk_size_gb: 4 - - - name: Delete managed disk - azure_rm_manageddisk: - name: mymanageddisk - location: eastus - resource_group: myResourceGroup - state: absent +- name: Create managed disk + azure_rm_manageddisk: + name: mymanageddisk + location: eastus + resource_group: myResourceGroup + disk_size_gb: 4 + +- name: Create managed operating system disk from page blob + azure_rm_manageddisk: + name: mymanageddisk + location: eastus2 + resource_group: myResourceGroup + create_option: import + source_uri: https://storageaccountname.blob.core.windows.net/containername/blob-name.vhd + storage_account_id: /subscriptions/<uuid>/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/storageaccountname + os_type: windows + storage_account_type: Premium_LRS + +- name: Mount the managed disk to VM + azure_rm_manageddisk: + name: mymanageddisk + location: eastus + resource_group: myResourceGroup + disk_size_gb: 4 + managed_by: testvm001 + attach_caching: read_only + +- name: Mount the managed disk to multiple VMs + azure_rm_manageddisk: + resource_group: myResourceGroup + name: freddisk04 + max_shares: 4 + disk_size_gb: 1024 + storage_account_type: Premium_LRS + managed_by_extended: + - resource_group: myResourceGroup01 + name: testVM01 + - resource_group: myResourceGroup02 + name: testVM02 + zone: 1 + +- name: Unmount the managed disk to VM + azure_rm_manageddisk: + name: mymanageddisk + location: eastus + resource_group: myResourceGroup + managed_by: '' + disk_size_gb: 4 + +- name: Delete managed disk + azure_rm_manageddisk: + name: mymanageddisk + location: eastus + resource_group: myResourceGroup + state: absent ''' RETURN = ''' @@ -278,14 +290,12 @@ changed: type: bool ''' -import re - from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: from concurrent.futures import ThreadPoolExecutor import multiprocessing - from msrestazure.tools import parse_resource_id + from azure.mgmt.core.tools import parse_resource_id from azure.core.exceptions import ResourceNotFoundError except ImportError: # This is handled in azure_rm_common @@ -569,7 +579,7 @@ class AzureRMManagedDisk(AzureRMModuleBase): if self.create_option == 'import': creation_data['create_option'] = self.compute_models.DiskCreateOption.import_enum creation_data['source_uri'] = self.source_uri - creation_data['source_account_id'] = self.storage_account_id + creation_data['storage_account_id'] = self.storage_account_id elif self.create_option == 'copy': creation_data['create_option'] = self.compute_models.DiskCreateOption.copy creation_data['source_resource_id'] = self.source_uri diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_manageddisk_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_manageddisk_info.py index 01656929c..be00c149e 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_manageddisk_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_manageddisk_info.py @@ -68,7 +68,7 @@ EXAMPLES = r''' - name: Get facts by tags azure_rm_manageddisk_info: tags: - - testing + - testing ''' RETURN = r''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_managementgroup.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_managementgroup.py index d9bee84fd..35235ccbe 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_managementgroup.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_managementgroup.py @@ -92,7 +92,6 @@ EXAMPLES = ''' azure_rm_managementgroup: group_id: ChildGroup state: absent - ''' RETURN = ''' @@ -270,6 +269,7 @@ class AzureRMManagementGroups(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) self.url = ('/providers' + @@ -359,9 +359,9 @@ class AzureRMManagementGroups(AzureRMModuleBaseExt): self.fail('Error creating the ManagementGroup instance: {0}'.format(str(exc))) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: - response = {'text': response.text} + response = {'text': response.context['deserialized_data']} pass return response @@ -396,7 +396,7 @@ class AzureRMManagementGroups(AzureRMModuleBaseExt): 600, 30) found = True - response = json.loads(response.text) + response = json.loads(response.body()) self.log("Response : {0}".format(response)) # self.log("ManagementGroup instance : {0} found".format(response.name)) except Exception as e: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_managementgroup_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_managementgroup_info.py index c95d10165..962d01831 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_managementgroup_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_managementgroup_info.py @@ -80,14 +80,14 @@ EXAMPLES = ''' - name: Get facts for one management group by id with direct children azure_rm_managementgroup_info: id: /providers/Microsoft.Management/managementGroups/contoso-group - children: True + children: true - name: Get facts for one management group by name with all children, flattened into top list azure_rm_managementgroup_info: name: "contoso-group" - children: True - recurse: True - flatten: True + children: true + recurse: true + flatten: true ''' RETURN = ''' @@ -257,7 +257,7 @@ class AzureRMManagementGroupInfo(AzureRMModuleBase): def to_dict(self, azure_object): if not azure_object: return [] - if azure_object.type == '/providers/Microsoft.Management/managementGroups': + if azure_object.type == 'Microsoft.Management/managementGroups': return_dict = dict( display_name=azure_object.display_name, id=azure_object.id, diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbconfiguration.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbconfiguration.py index 69d6d509a..f00085600 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbconfiguration.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbconfiguration.py @@ -55,12 +55,12 @@ author: ''' EXAMPLES = ''' - - name: Update SQL Server setting - azure_rm_mariadbconfiguration: - resource_group: myResourceGroup - server_name: myServer - name: event_scheduler - value: "ON" +- name: Update SQL Server setting + azure_rm_mariadbconfiguration: + resource_group: myResourceGroup + server_name: myServer + name: event_scheduler + value: "ON" ''' RETURN = ''' @@ -73,13 +73,11 @@ id: gurations/event_scheduler" ''' -import time from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbconfiguration_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbconfiguration_info.py index a1165d3f7..854d4854e 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbconfiguration_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbconfiguration_info.py @@ -43,16 +43,16 @@ author: ''' EXAMPLES = ''' - - name: Get specific setting of MariaDB Server - azure_rm_mariadbconfiguration_info: - resource_group: myResourceGroup - server_name: testserver - name: deadlock_timeout - - - name: Get all settings of MariaDB Server - azure_rm_mariadbconfiguration_info: - resource_group: myResourceGroup - server_name: server_name +- name: Get specific setting of MariaDB Server + azure_rm_mariadbconfiguration_info: + resource_group: myResourceGroup + server_name: testserver + name: deadlock_timeout + +- name: Get all settings of MariaDB Server + azure_rm_mariadbconfiguration_info: + resource_group: myResourceGroup + server_name: server_name ''' RETURN = ''' @@ -97,9 +97,7 @@ settings: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: - from msrestazure.azure_operation import AzureOperationPoller from azure.core.exceptions import ResourceNotFoundError - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbdatabase.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbdatabase.py index d97e1a2dd..60a5fccd4 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbdatabase.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbdatabase.py @@ -22,32 +22,38 @@ options: description: - The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal. required: True + type: str server_name: description: - The name of the server. required: True + type: str name: description: - The name of the database. required: True + type: str charset: description: - The charset of the database. Check MariaDB documentation for possible values. - This is only set on creation, use I(force_update) to recreate a database if the values don't match. + type: str collation: description: - The collation of the database. Check MariaDB documentation for possible values. - This is only set on creation, use I(force_update) to recreate a database if the values don't match. + type: str force_update: - description: - - When set to C(true), will delete and recreate the existing MariaDB database if any of the properties don't match what is set. - - When set to C(false), no change will occur to the database even if any of the properties do not match. - type: bool - default: 'no' + description: + - When set to C(true), will delete and recreate the existing MariaDB database if any of the properties don't match what is set. + - When set to C(false), no change will occur to the database even if any of the properties do not match. + type: bool + default: 'no' state: description: - Assert the state of the MariaDB Database. Use C(present) to create or update a database and C(absent) to delete it. default: present + type: str choices: - absent - present @@ -62,11 +68,11 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) MariaDB Database - azure_rm_mariadbdatabase: - resource_group: myResourceGroup - server_name: testserver - name: db1 +- name: Create (or update) MariaDB Database + azure_rm_mariadbdatabase: + resource_group: myResourceGroup + server_name: testserver + name: db1 ''' RETURN = ''' @@ -90,7 +96,6 @@ try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbdatabase_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbdatabase_info.py index 02e005119..4551122bb 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbdatabase_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbdatabase_info.py @@ -43,16 +43,16 @@ author: ''' EXAMPLES = ''' - - name: Get instance of MariaDB Database - azure_rm_mariadbdatabase_info: - resource_group: myResourceGroup - server_name: server_name - name: database_name - - - name: List instances of MariaDB Database - azure_rm_mariadbdatabase_info: - resource_group: myResourceGroup - server_name: server_name +- name: Get instance of MariaDB Database + azure_rm_mariadbdatabase_info: + resource_group: myResourceGroup + server_name: server_name + name: database_name + +- name: List instances of MariaDB Database + azure_rm_mariadbdatabase_info: + resource_group: myResourceGroup + server_name: server_name ''' RETURN = ''' @@ -104,7 +104,6 @@ databases: try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbfirewallrule.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbfirewallrule.py index 0424db9f7..f634ab386 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbfirewallrule.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbfirewallrule.py @@ -22,24 +22,30 @@ options: description: - The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal. required: True + type: str server_name: description: - The name of the server. required: True + type: str name: description: - The name of the MariaDB firewall rule. required: True + type: str start_ip_address: description: - The start IP address of the MariaDB firewall rule. Must be IPv4 format. + type: str end_ip_address: description: - The end IP address of the MariaDB firewall rule. Must be IPv4 format. + type: str state: description: - Assert the state of the MariaDB firewall rule. Use C(present) to create or update a rule and C(absent) to ensure it is not present. default: present + type: str choices: - absent - present @@ -54,13 +60,13 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) MariaDB firewall rule - azure_rm_mariadbfirewallrule: - resource_group: myResourceGroup - server_name: testserver - name: rule1 - start_ip_address: 10.0.0.17 - end_ip_address: 10.0.0.20 +- name: Create (or update) MariaDB firewall rule + azure_rm_mariadbfirewallrule: + resource_group: myResourceGroup + server_name: testserver + name: rule1 + start_ip_address: 10.0.0.17 + end_ip_address: 10.0.0.20 ''' RETURN = ''' @@ -79,7 +85,6 @@ try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbfirewallrule_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbfirewallrule_info.py index ad7f979c5..5444c2557 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbfirewallrule_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbfirewallrule_info.py @@ -43,16 +43,16 @@ author: ''' EXAMPLES = ''' - - name: Get instance of MariaDB Firewall Rule - azure_rm_mariadbfirewallrule_info: - resource_group: myResourceGroup - server_name: server_name - name: firewall_rule_name - - - name: List instances of MariaDB Firewall Rule - azure_rm_mariadbfirewallrule_info: - resource_group: myResourceGroup - server_name: server_name +- name: Get instance of MariaDB Firewall Rule + azure_rm_mariadbfirewallrule_info: + resource_group: myResourceGroup + server_name: server_name + name: firewall_rule_name + +- name: List instances of MariaDB Firewall Rule + azure_rm_mariadbfirewallrule_info: + resource_group: myResourceGroup + server_name: server_name ''' RETURN = ''' @@ -97,9 +97,7 @@ rules: try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase - from msrestazure.azure_operation import AzureOperationPoller from azure.core.exceptions import ResourceNotFoundError - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbserver.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbserver.py index 3e1b838cc..ed6b423ff 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbserver.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbserver.py @@ -22,20 +22,25 @@ options: description: - The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal. required: True + type: str name: description: - The name of the server. required: True + type: str sku: description: - The SKU (pricing tier) of the server. + type: dict suboptions: name: description: - The name of the SKU, typically, tier + family + cores, for example C(B_Gen4_1), C(GP_Gen5_8). + type: str tier: description: - The tier of the particular SKU, for example C(Basic). + type: str choices: - basic - standard @@ -49,6 +54,7 @@ options: location: description: - Resource location. If not set, location from the resource group will be used as default. + type: str storage_mb: description: - The maximum storage allowed for a server. @@ -56,9 +62,10 @@ options: version: description: - Server version. + type: str choices: - - 10.2 - - 10.3 + - '10.2' + - '10.3' enforce_ssl: description: - Enable SSL enforcement. @@ -67,17 +74,21 @@ options: admin_username: description: - The administrator's login name of a server. Can only be specified when the server is being created (and is required for creation). + type: str admin_password: description: - The password of the administrator login. + type: str create_mode: description: - Create mode of SQL Server. + type: str default: Default state: description: - Assert the state of the MariaDB Server. Use C(present) to create or update a server and C(absent) to delete it. default: present + type: str choices: - absent - present @@ -93,19 +104,19 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) MariaDB Server - azure_rm_mariadbserver: - resource_group: myResourceGroup - name: testserver - sku: - name: B_Gen5_1 - tier: Basic - location: eastus - storage_mb: 1024 - enforce_ssl: True - version: 10.2 - admin_username: cloudsa - admin_password: password +- name: Create (or update) MariaDB Server + azure_rm_mariadbserver: + resource_group: myResourceGroup + name: testserver + sku: + name: B_Gen5_1 + tier: Basic + location: eastus + storage_mb: 1024 + enforce_ssl: true + version: 10.2 + admin_username: cloudsa + admin_password: password ''' RETURN = ''' @@ -141,7 +152,6 @@ try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbserver_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbserver_info.py index e5aa0c88f..57c80b2b8 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbserver_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mariadbserver_info.py @@ -43,16 +43,16 @@ author: ''' EXAMPLES = ''' - - name: Get instance of MariaDB Server - azure_rm_mariadbserver_info: - resource_group: myResourceGroup - name: server_name +- name: Get instance of MariaDB Server + azure_rm_mariadbserver_info: + resource_group: myResourceGroup + name: server_name - - name: List instances of MariaDB Server - azure_rm_mariadbserver_info: - resource_group: myResourceGroup - tags: - - key:value +- name: List instances of MariaDB Server + azure_rm_mariadbserver_info: + resource_group: myResourceGroup + tags: + - key:value ''' RETURN = ''' @@ -156,7 +156,6 @@ servers: try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_monitordiagnosticsetting.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_monitordiagnosticsetting.py index 0f08eff9a..534b41bc5 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_monitordiagnosticsetting.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_monitordiagnosticsetting.py @@ -354,7 +354,7 @@ state: ''' try: - from msrestazure.tools import (parse_resource_id, resource_id) + from azure.mgmt.core.tools import (parse_resource_id, resource_id) from azure.core.polling import LROPoller except ImportError: # This is handled in azure_rm_common diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_monitordiagnosticsetting_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_monitordiagnosticsetting_info.py index f7081ce79..53a971654 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_monitordiagnosticsetting_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_monitordiagnosticsetting_info.py @@ -212,7 +212,7 @@ settings: ''' try: - from msrestazure.tools import (parse_resource_id, resource_id) + from azure.mgmt.core.tools import (parse_resource_id, resource_id) except Exception: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_monitorlogprofile.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_monitorlogprofile.py index a224c1fba..349ec52f5 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_monitorlogprofile.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_monitorlogprofile.py @@ -80,28 +80,28 @@ author: ''' EXAMPLES = ''' - - name: Create a log profile - azure_rm_monitorlogprofile: - name: myProfile - location: eastus - locations: - - eastus - - westus - categories: - - Write - - Action - retention_policy: - enabled: False - days: 1 - storage_account: - resource_group: myResourceGroup - name: myStorageAccount - register: output - - - name: Delete a log profile - azure_rm_monitorlogprofile: - name: myProfile - state: absent +- name: Create a log profile + azure_rm_monitorlogprofile: + name: myProfile + location: eastus + locations: + - eastus + - westus + categories: + - Write + - Action + retention_policy: + enabled: false + days: 1 + storage_account: + resource_group: myResourceGroup + name: myStorageAccount + register: output + +- name: Delete a log profile + azure_rm_monitorlogprofile: + name: myProfile + state: absent ''' RETURN = ''' @@ -114,13 +114,12 @@ id: ''' -import time try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, format_resource_id from azure.core.exceptions import HttpResponseError from azure.core.polling import LROPoller - from msrestazure.tools import is_valid_resource_id + from azure.mgmt.core.tools import is_valid_resource_id from azure.mgmt.monitor.models import (RetentionPolicy, LogProfileResource) except ImportError: # This is handled in azure_rm_common diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_multiplemanageddisks.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_multiplemanageddisks.py index 76a57a659..519a3e38a 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_multiplemanageddisks.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_multiplemanageddisks.py @@ -165,77 +165,77 @@ author: ''' EXAMPLES = ''' - - name: Create managed operating system disks from page blob and attach them to a list of VMs - azure_rm_multiplemanageddisks: - managed_disks: - - name: mymanageddisk1 - location: eastus2 - resource_group: myResourceGroup - create_option: import - source_uri: https://storageaccountname.blob.core.windows.net/containername/blob-name.vhd - storage_account_id: /subscriptions/<uuid>/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/storageaccountname - os_type: windows - storage_account_type: Premium_LRS - - name: mymanageddisk2 - location: eastus2 - resource_group: myResourceGroup - create_option: import - source_uri: https://storageaccountname.blob.core.windows.net/containername/blob-name.vhd - storage_account_id: /subscriptions/<uuid>/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/storageaccountname - os_type: windows - storage_account_type: Premium_LRS - managed_by_extended: - - resource_group: myResourceGroupTest - name: TestVM - - - name: Detach disks from the VMs specified in the list - azure_rm_multiplemanageddisks: - state: absent - managed_disks: - - name: mymanageddisk1 - location: eastus2 - resource_group: myResourceGroup - create_option: import - source_uri: https://storageaccountname.blob.core.windows.net/containername/blob-name.vhd - storage_account_id: /subscriptions/<uuid>/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/storageaccountname - os_type: windows - storage_account_type: Premium_LRS - - name: mymanageddisk2 - location: eastus2 - resource_group: myResourceGroup - create_option: import - source_uri: https://storageaccountname.blob.core.windows.net/containername/blob-name.vhd - storage_account_id: /subscriptions/<uuid>/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/storageaccountname - os_type: windows - storage_account_type: Premium_LRS - managed_by_extended: - - resource_group: myResourceGroupTest - name: TestVM1 - - resource_group: myResourceGroupTest - name: TestVM2 - - - name: Detach managed disks from all VMs without deletion - azure_rm_multiplemanageddisks: - state: present - managed_disks: - - name: mymanageddisk1 - location: eastus2 - resource_group: myResourceGroup - - name: mymanageddisk2 - location: eastus2 - resource_group: myResourceGroup - managed_by_extended: [] - - - name: Detach managed disks from all VMs and delete them - azure_rm_multiplemanageddisks: - state: absent - managed_disks: - - name: mymanageddisk1 - location: eastus2 - resource_group: myResourceGroup - - name: mymanageddisk2 - location: eastus2 - resource_group: myResourceGroup +- name: Create managed operating system disks from page blob and attach them to a list of VMs + azure_rm_multiplemanageddisks: + managed_disks: + - name: mymanageddisk1 + location: eastus2 + resource_group: myResourceGroup + create_option: import + source_uri: https://storageaccountname.blob.core.windows.net/containername/blob-name.vhd + storage_account_id: /subscriptions/<uuid>/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/storageaccountname + os_type: windows + storage_account_type: Premium_LRS + - name: mymanageddisk2 + location: eastus2 + resource_group: myResourceGroup + create_option: import + source_uri: https://storageaccountname.blob.core.windows.net/containername/blob-name.vhd + storage_account_id: /subscriptions/<uuid>/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/storageaccountname + os_type: windows + storage_account_type: Premium_LRS + managed_by_extended: + - resource_group: myResourceGroupTest + name: TestVM + +- name: Detach disks from the VMs specified in the list + azure_rm_multiplemanageddisks: + state: absent + managed_disks: + - name: mymanageddisk1 + location: eastus2 + resource_group: myResourceGroup + create_option: import + source_uri: https://storageaccountname.blob.core.windows.net/containername/blob-name.vhd + storage_account_id: /subscriptions/<uuid>/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/storageaccountname + os_type: windows + storage_account_type: Premium_LRS + - name: mymanageddisk2 + location: eastus2 + resource_group: myResourceGroup + create_option: import + source_uri: https://storageaccountname.blob.core.windows.net/containername/blob-name.vhd + storage_account_id: /subscriptions/<uuid>/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/storageaccountname + os_type: windows + storage_account_type: Premium_LRS + managed_by_extended: + - resource_group: myResourceGroupTest + name: TestVM1 + - resource_group: myResourceGroupTest + name: TestVM2 + +- name: Detach managed disks from all VMs without deletion + azure_rm_multiplemanageddisks: + state: present + managed_disks: + - name: mymanageddisk1 + location: eastus2 + resource_group: myResourceGroup + - name: mymanageddisk2 + location: eastus2 + resource_group: myResourceGroup + managed_by_extended: [] + +- name: Detach managed disks from all VMs and delete them + azure_rm_multiplemanageddisks: + state: absent + managed_disks: + - name: mymanageddisk1 + location: eastus2 + resource_group: myResourceGroup + - name: mymanageddisk2 + location: eastus2 + resource_group: myResourceGroup ''' RETURN = ''' @@ -312,7 +312,7 @@ state: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: from azure.core.exceptions import ResourceNotFoundError, AzureError - from msrestazure.tools import parse_resource_id + from azure.mgmt.core.tools import parse_resource_id import time except ImportError: # This is handled in azure_rm_common @@ -456,7 +456,7 @@ class AzureRMMultipleManagedDisk(AzureRMModuleBase): if create_option == 'import': creation_data['create_option'] = self.compute_models.DiskCreateOption.import_enum creation_data['source_uri'] = source_uri - creation_data['source_account_id'] = storage_account_id + creation_data['storage_account_id'] = storage_account_id elif create_option == 'copy': creation_data['create_option'] = self.compute_models.DiskCreateOption.copy creation_data['source_resource_id'] = source_uri diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlconfiguration.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlconfiguration.py index 6f4f477ab..9137f591b 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlconfiguration.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlconfiguration.py @@ -21,21 +21,26 @@ options: description: - The name of the resource group that contains the resource. required: True + type: str server_name: description: - The name of the server. required: True + type: str name: description: - The name of the server configuration. required: True + type: str value: description: - Value of the configuration. + type: str state: description: - Assert the state of the MySQL configuration. Use C(present) to update setting, or C(absent) to reset to default value. default: present + type: str choices: - absent - present @@ -49,12 +54,12 @@ author: ''' EXAMPLES = ''' - - name: Update SQL Server setting - azure_rm_mysqlconfiguration: - resource_group: myResourceGroup - server_name: myServer - name: event_scheduler - value: "ON" +- name: Update SQL Server setting + azure_rm_mysqlconfiguration: + resource_group: myResourceGroup + server_name: myServer + name: event_scheduler + value: "ON" ''' RETURN = ''' @@ -67,13 +72,10 @@ id: gurations/event_scheduler" ''' -import time - try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlconfiguration_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlconfiguration_info.py index 48fa416a4..f6cd01ea9 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlconfiguration_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlconfiguration_info.py @@ -41,16 +41,16 @@ author: ''' EXAMPLES = ''' - - name: Get specific setting of MySQL Server - azure_rm_mysqlconfiguration_info: - resource_group: myResourceGroup - server_name: testmysqlserver - name: deadlock_timeout - - - name: Get all settings of MySQL Server - azure_rm_mysqlconfiguration_info: - resource_group: myResourceGroup - server_name: server_name +- name: Get specific setting of MySQL Server + azure_rm_mysqlconfiguration_info: + resource_group: myResourceGroup + server_name: testmysqlserver + name: deadlock_timeout + +- name: Get all settings of MySQL Server + azure_rm_mysqlconfiguration_info: + resource_group: myResourceGroup + server_name: server_name ''' RETURN = ''' @@ -95,9 +95,7 @@ settings: try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase - from msrestazure.azure_operation import AzureOperationPoller from azure.core.exceptions import ResourceNotFoundError - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqldatabase.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqldatabase.py index 09f28fc02..a8caa1745 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqldatabase.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqldatabase.py @@ -21,22 +21,27 @@ options: description: - The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal. required: True + type: str server_name: description: - The name of the server. required: True + type: str name: description: - The name of the database. required: True + type: str charset: description: - The charset of the database. Check MySQL documentation for possible values. - This is only set on creation, use I(force_update) to recreate a database if the values don't match. + type: str collation: description: - The collation of the database. Check MySQL documentation for possible values. - This is only set on creation, use I(force_update) to recreate a database if the values don't match. + type: str force_update: description: - When set to C(true), will delete and recreate the existing MySQL database if any of the properties don't match what is set. @@ -47,6 +52,7 @@ options: description: - Assert the state of the MySQL Database. Use C(present) to create or update a database and C(absent) to delete it. default: present + type: str choices: - absent - present @@ -60,11 +66,11 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) MySQL Database - azure_rm_mysqldatabase: - resource_group: myResourceGroup - server_name: testserver - name: db1 +- name: Create (or update) MySQL Database + azure_rm_mysqldatabase: + resource_group: myResourceGroup + server_name: testserver + name: db1 ''' RETURN = ''' @@ -88,7 +94,6 @@ try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqldatabase_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqldatabase_info.py index 9c53a686a..db2cb8cdf 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqldatabase_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqldatabase_info.py @@ -41,16 +41,16 @@ author: ''' EXAMPLES = ''' - - name: Get instance of MySQL Database - azure_rm_mysqldatabase_info: - resource_group: myResourceGroup - server_name: server_name - name: database_name - - - name: List instances of MySQL Database - azure_rm_mysqldatabase_info: - resource_group: myResourceGroup - server_name: server_name +- name: Get instance of MySQL Database + azure_rm_mysqldatabase_info: + resource_group: myResourceGroup + server_name: server_name + name: database_name + +- name: List instances of MySQL Database + azure_rm_mysqldatabase_info: + resource_group: myResourceGroup + server_name: server_name ''' RETURN = ''' @@ -102,8 +102,6 @@ databases: try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError - from azure.core.polling import LROPoller - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlfirewallrule.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlfirewallrule.py index ef5765718..a17e8cc1f 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlfirewallrule.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlfirewallrule.py @@ -21,26 +21,32 @@ options: description: - The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal. required: True + type: str server_name: description: - The name of the server. required: True + type: str name: description: - The name of the MySQL firewall rule. required: True + type: str start_ip_address: description: - The start IP address of the MySQL firewall rule. Must be IPv4 format. - required: True + - Required when creating. + type: str end_ip_address: description: - The end IP address of the MySQL firewall rule. Must be IPv4 format. - required: True + - Required when creating. + type: str state: description: - Assert the state of the MySQL firewall rule. Use C(present) to create or update a rule and C(absent) to ensure it is not present. default: present + type: str choices: - absent - present @@ -54,13 +60,13 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) MySQL firewall rule - azure_rm_mysqlfirewallrule: - resource_group: myResourceGroup - server_name: testserver - name: rule1 - start_ip_address: 10.0.0.17 - end_ip_address: 10.0.0.20 +- name: Create (or update) MySQL firewall rule + azure_rm_mysqlfirewallrule: + resource_group: myResourceGroup + server_name: testserver + name: rule1 + start_ip_address: 10.0.0.17 + end_ip_address: 10.0.0.20 ''' RETURN = ''' @@ -79,7 +85,6 @@ try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass @@ -125,6 +130,7 @@ class AzureRMMySqlFirewallRule(AzureRMModuleBase): self.start_ip_address = None self.end_ip_address = None + required_if = [('state', 'present', ['start_ip_address', 'end_ip_address'])] self.results = dict(changed=False) self.state = None self.parameters = dict() @@ -132,6 +138,7 @@ class AzureRMMySqlFirewallRule(AzureRMModuleBase): super(AzureRMMySqlFirewallRule, self).__init__(derived_arg_spec=self.module_arg_spec, supports_check_mode=True, + required_if=required_if, supports_tags=False) def exec_module(self, **kwargs): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlfirewallrule_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlfirewallrule_info.py index 5bc8c1aff..9ee597780 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlfirewallrule_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlfirewallrule_info.py @@ -41,16 +41,16 @@ author: ''' EXAMPLES = ''' - - name: Get instance of MySQL Firewall Rule - azure_rm_mysqlfirewallrule_info: - resource_group: myResourceGroup - server_name: server_name - name: firewall_rule_name - - - name: List instances of MySQL Firewall Rule - azure_rm_mysqlfirewallrule_info: - resource_group: myResourceGroup - server_name: server_name +- name: Get instance of MySQL Firewall Rule + azure_rm_mysqlfirewallrule_info: + resource_group: myResourceGroup + server_name: server_name + name: firewall_rule_name + +- name: List instances of MySQL Firewall Rule + azure_rm_mysqlfirewallrule_info: + resource_group: myResourceGroup + server_name: server_name ''' RETURN = ''' @@ -95,9 +95,7 @@ rules: try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase - from msrestazure.azure_operation import AzureOperationPoller from azure.core.exceptions import ResourceNotFoundError - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlserver.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlserver.py index 49bfee6a6..f972f29a8 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlserver.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlserver.py @@ -132,23 +132,23 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) MySQL Server - azure_rm_mysqlserver: - resource_group: myResourceGroup - name: testserver - sku: - name: B_Gen5_1 - tier: Basic - location: eastus - storage_profile: - storage_mb: 51200 - backup_retention_days: 7 - geo_redundant_backup: Disabled - storage_autogrow: Disabled - enforce_ssl: True - version: 5.7 - admin_username: cloudsa - admin_password: password +- name: Create (or update) MySQL Server + azure_rm_mysqlserver: + resource_group: myResourceGroup + name: testserver + sku: + name: B_Gen5_1 + tier: Basic + location: eastus + storage_profile: + storage_mb: 51200 + backup_retention_days: 7 + geo_redundant_backup: Disabled + storage_autogrow: Disabled + enforce_ssl: true + version: 5.7 + admin_username: cloudsa + admin_password: password ''' RETURN = ''' @@ -184,7 +184,6 @@ try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlserver_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlserver_info.py index 503219cb8..4a0b91c00 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlserver_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqlserver_info.py @@ -41,16 +41,16 @@ author: ''' EXAMPLES = ''' - - name: Get instance of MySQL Server - azure_rm_mysqlserver_info: - resource_group: myResourceGroup - name: server_name - tags: - - key +- name: Get instance of MySQL Server + azure_rm_mysqlserver_info: + resource_group: myResourceGroup + name: server_name + tags: + - key - - name: List instances of MySQL Server - azure_rm_mysqlserver_info: - resource_group: myResourceGroup +- name: List instances of MySQL Server + azure_rm_mysqlserver_info: + resource_group: myResourceGroup ''' RETURN = ''' @@ -178,7 +178,6 @@ servers: try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_natgateway.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_natgateway.py index e4dd46ade..e53f4fddf 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_natgateway.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_natgateway.py @@ -94,7 +94,7 @@ EXAMPLES = """ name: myNATGateway idle_timeout_in_minutes: 10 location: eastus - zones: [ 1 ] + zones: [1] sku: name: standard """ @@ -132,7 +132,7 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from msrestazure.tools import parse_resource_id, is_valid_resource_id + from azure.mgmt.core.tools import parse_resource_id, is_valid_resource_id except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_natgateway_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_natgateway_info.py index 262dd2d99..27271303a 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_natgateway_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_natgateway_info.py @@ -33,17 +33,17 @@ author: ''' EXAMPLES = ''' - - name: Get facts for NAT gateway by name. - azure_rm_natgateway_info: - name: Mynatgw - resource_group: MyResourceGroup +- name: Get facts for NAT gateway by name. + azure_rm_natgateway_info: + name: Mynatgw + resource_group: MyResourceGroup - - name: Get facts for all NAT gateways in resource group. - azure_rm_natgateway_info: - resource_group: MyResourceGroup +- name: Get facts for all NAT gateways in resource group. + azure_rm_natgateway_info: + resource_group: MyResourceGroup - - name: Get facts for all NAT gateways. - azure_rm_natgateway_info: +- name: Get facts for all NAT gateways. + azure_rm_natgateway_info: ''' RETURN = ''' @@ -114,7 +114,7 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError - from msrestazure.tools import parse_resource_id + from azure.mgmt.core.tools import parse_resource_id except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_networkinterface.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_networkinterface.py index bd988f06a..bb17132d4 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_networkinterface.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_networkinterface.py @@ -30,21 +30,25 @@ options: description: - Name of a resource group where the network interface exists or will be created. required: true + type: str name: description: - Name of the network interface. required: true + type: str state: description: - Assert the state of the network interface. Use C(present) to create or update an interface and C(absent) to delete an interface. default: present + type: str choices: - absent - present location: description: - Valid Azure location. Defaults to location of the resource group. + type: str virtual_network: description: - An existing virtual network with which the network interface will be associated. Required when creating a network interface. @@ -52,22 +56,25 @@ options: - Make sure your virtual network is in the same resource group as NIC when you give only the name. - It can be the virtual network's resource id. - It can be a dict which contains I(name) and I(resource_group) of the virtual network. + - Required when creating. + type: raw aliases: - virtual_network_name - required: true subnet_name: description: - Name of an existing subnet within the specified virtual network. Required when creating a network interface. - Use the C(virtual_network)'s resource group. + - Required when creating. aliases: - subnet - required: true + type: str os_type: description: - Determines any rules to be added to a default security group. - When creating a network interface, if no security group name is provided, a default security group will be created. - If the I(os_type=Windows), a rule allowing RDP access will be added. - If the I(os_type=Linux), a rule allowing SSH access will be added. + type: str choices: - Windows - Linux @@ -76,6 +83,7 @@ options: description: - (Deprecate) Valid IPv4 address that falls within the specified subnet. - This option will be deprecated in 2.9, use I(ip_configurations) instead. + type: str private_ip_allocation_method: description: - (Deprecate) Whether or not the assigned IP address is permanent. @@ -83,6 +91,7 @@ options: - You can update the allocation method to C(Static) after a dynamic private IP address has been assigned. - This option will be deprecated in 2.9, use I(ip_configurations) instead. default: Dynamic + type: str choices: - Dynamic - Static @@ -97,6 +106,7 @@ options: description: - (Deprecate) Name of an existing public IP address object to associate with the security group. - This option will be deprecated in 2.9, use I(ip_configurations) instead. + type: str aliases: - public_ip_address - public_ip_name @@ -105,6 +115,7 @@ options: - (Deprecate) If a I(public_ip_address_name) is not provided, a default public IP address will be created. - The allocation method determines whether or not the public IP address assigned to the network interface is permanent. - This option will be deprecated in 2.9, use I(ip_configurations) instead. + type: str choices: - Dynamic - Static @@ -113,17 +124,23 @@ options: description: - List of IP configurations. Each configuration object should include field I(private_ip_address), I(private_ip_allocation_method), I(public_ip_address_name), I(public_ip), I(public_ip_allocation_method), I(name). + type: list + elements: dict + default: [] suboptions: name: description: - Name of the IP configuration. required: true + type: str private_ip_address: description: - Private IP address for the IP configuration. + type: str private_ip_address_version: description: - The version of the IP configuration. + type: str choices: - IPv4 - IPv6 @@ -131,6 +148,7 @@ options: private_ip_allocation_method: description: - Private IP allocation method. + type: str choices: - Dynamic - Static @@ -138,12 +156,14 @@ options: public_ip_address_name: description: - Name of the public IP address. None for disable IP address. + type: str aliases: - public_ip_address - public_ip_name public_ip_allocation_method: description: - Public IP allocation method. + type: str choices: - Dynamic - Static @@ -153,11 +173,15 @@ options: - List of existing load-balancer backend address pools to associate with the network interface. - Can be written as a resource ID. - Also can be a dict of I(name) and I(load_balancer). + type: list + elements: raw application_gateway_backend_address_pools: description: - List of existing application gateway backend address pools to associate with the network interface. - Can be written as a resource ID. - Also can be a dict of I(name) and I(application_gateway). + type: list + elements: raw version_added: "1.10.0" primary: description: @@ -169,6 +193,8 @@ options: description: - List of application security groups in which the IP configuration is included. - Element of the list could be a resource id of application security group, or dict of I(resource_group) and I(name). + type: list + elements: raw enable_accelerated_networking: description: - Whether the network interface should be created with the accelerated networking feature or not. @@ -190,11 +216,14 @@ options: - It can be a dict contains security_group's I(name) and I(resource_group). aliases: - security_group_name + type: raw open_ports: description: - When a default security group is created for a Linux host a rule will be added allowing inbound TCP connections to the default SSH port C(22), and for a Windows host rules will be added allowing inbound access to RDP ports C(3389) and C(5986). Override the default ports by providing a list of open ports. + type: list + elements: str enable_ip_forwarding: description: - Whether to enable IP forwarding. @@ -207,6 +236,7 @@ options: - Which DNS servers should the NIC lookup. - List of IP addresses. type: list + elements: str extends_documentation_fragment: - azure.azcollection.azure - azure.azcollection.azure_tags @@ -218,123 +248,123 @@ author: ''' EXAMPLES = ''' - - name: Create a network interface with minimal parameters - azure_rm_networkinterface: - name: nic001 - resource_group: myResourceGroup - virtual_network: vnet001 - subnet_name: subnet001 - ip_configurations: - - name: ipconfig1 - public_ip_address_name: publicip001 - primary: True - - - name: Create a network interface with private IP address only (no Public IP) - azure_rm_networkinterface: - name: nic001 - resource_group: myResourceGroup - virtual_network: vnet001 - subnet_name: subnet001 - create_with_security_group: False - ip_configurations: - - name: ipconfig1 - primary: True - - - name: Create a network interface for use in a Windows host (opens RDP port) with custom RDP port - azure_rm_networkinterface: - name: nic002 - resource_group: myResourceGroup - virtual_network: vnet001 - subnet_name: subnet001 - os_type: Windows - rdp_port: 3399 - security_group: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroup/myResourceGroup/providers/Microsoft.Network/networkSecurit - yGroups/nsg001" - ip_configurations: - - name: ipconfig1 - public_ip_address_name: publicip001 - primary: True - - - name: Create a network interface using existing security group and public IP - azure_rm_networkinterface: - name: nic003 - resource_group: myResourceGroup - virtual_network: vnet001 - subnet_name: subnet001 - security_group: secgroup001 - ip_configurations: - - name: ipconfig1 - public_ip_address_name: publicip001 - primary: True - - - name: Create a network with multiple ip configurations - azure_rm_networkinterface: - name: nic004 - resource_group: myResourceGroup - subnet_name: subnet001 - virtual_network: vnet001 - security_group: - name: testnic002 - resource_group: Testing1 - ip_configurations: - - name: ipconfig1 - public_ip_address_name: publicip001 - primary: True - - name: ipconfig2 - load_balancer_backend_address_pools: - - "{{ loadbalancer001.state.backend_address_pools[0].id }}" - - name: backendaddrpool1 - load_balancer: loadbalancer001 - - - name: Create network interface attached to application gateway backend address pool - azure_rm_networkinterface: - name: nic-appgw - resource_group: myResourceGroup - virtual_network: vnet001 - subnet_name: subnet001 - create_with_security_group: false - public_ip: false - ip_configurations: - - name: default - primary: true - application_gateway_backend_address_pools: - - name: myApplicationGatewayBackendAddressPool - application_gateway: myApplicationGateway - - - name: Create a network interface in accelerated networking mode - azure_rm_networkinterface: - name: nic005 - resource_group: myResourceGroup - virtual_network_name: vnet001 - subnet_name: subnet001 - enable_accelerated_networking: True - - - name: Create a network interface with IP forwarding - azure_rm_networkinterface: - name: nic001 - resource_group: myResourceGroup - virtual_network: vnet001 - subnet_name: subnet001 - ip_forwarding: True - ip_configurations: - - name: ipconfig1 - public_ip_address_name: publicip001 - primary: True - - - name: Create a network interface with dns servers - azure_rm_networkinterface: - name: nic009 - resource_group: myResourceGroup - virtual_network: vnet001 - subnet_name: subnet001 - dns_servers: - - 8.8.8.8 - - - name: Delete network interface - azure_rm_networkinterface: - resource_group: myResourceGroup - name: nic003 - state: absent +- name: Create a network interface with minimal parameters + azure_rm_networkinterface: + name: nic001 + resource_group: myResourceGroup + virtual_network: vnet001 + subnet_name: subnet001 + ip_configurations: + - name: ipconfig1 + public_ip_address_name: publicip001 + primary: true + +- name: Create a network interface with private IP address only (no Public IP) + azure_rm_networkinterface: + name: nic001 + resource_group: myResourceGroup + virtual_network: vnet001 + subnet_name: subnet001 + create_with_security_group: false + ip_configurations: + - name: ipconfig1 + primary: true + +- name: Create a network interface for use in a Windows host (opens RDP port) with custom RDP port + azure_rm_networkinterface: + name: nic002 + resource_group: myResourceGroup + virtual_network: vnet001 + subnet_name: subnet001 + os_type: Windows + rdp_port: 3399 + security_group: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroup/myResourceGroup/providers/Microsoft.Network/networkSecurit + yGroups/nsg001" + ip_configurations: + - name: ipconfig1 + public_ip_address_name: publicip001 + primary: true + +- name: Create a network interface using existing security group and public IP + azure_rm_networkinterface: + name: nic003 + resource_group: myResourceGroup + virtual_network: vnet001 + subnet_name: subnet001 + security_group: secgroup001 + ip_configurations: + - name: ipconfig1 + public_ip_address_name: publicip001 + primary: true + +- name: Create a network with multiple ip configurations + azure_rm_networkinterface: + name: nic004 + resource_group: myResourceGroup + subnet_name: subnet001 + virtual_network: vnet001 + security_group: + name: testnic002 + resource_group: Testing1 + ip_configurations: + - name: ipconfig1 + public_ip_address_name: publicip001 + primary: true + - name: ipconfig2 + load_balancer_backend_address_pools: + - "{{ loadbalancer001.state.backend_address_pools[0].id }}" + - name: backendaddrpool1 + load_balancer: loadbalancer001 + +- name: Create network interface attached to application gateway backend address pool + azure_rm_networkinterface: + name: nic-appgw + resource_group: myResourceGroup + virtual_network: vnet001 + subnet_name: subnet001 + create_with_security_group: false + public_ip: false + ip_configurations: + - name: default + primary: true + application_gateway_backend_address_pools: + - name: myApplicationGatewayBackendAddressPool + application_gateway: myApplicationGateway + +- name: Create a network interface in accelerated networking mode + azure_rm_networkinterface: + name: nic005 + resource_group: myResourceGroup + virtual_network_name: vnet001 + subnet_name: subnet001 + enable_accelerated_networking: true + +- name: Create a network interface with IP forwarding + azure_rm_networkinterface: + name: nic001 + resource_group: myResourceGroup + virtual_network: vnet001 + subnet_name: subnet001 + ip_forwarding: true + ip_configurations: + - name: ipconfig1 + public_ip_address_name: publicip001 + primary: true + +- name: Create a network interface with dns servers + azure_rm_networkinterface: + name: nic009 + resource_group: myResourceGroup + virtual_network: vnet001 + subnet_name: subnet001 + dns_servers: + - 8.8.8.8 + +- name: Delete network interface + azure_rm_networkinterface: + resource_group: myResourceGroup + name: nic003 + state: absent ''' RETURN = ''' @@ -485,7 +515,7 @@ state: ''' try: - from msrestazure.tools import parse_resource_id, resource_id, is_valid_resource_id + from azure.mgmt.core.tools import resource_id, is_valid_resource_id from azure.core.exceptions import ResourceNotFoundError except ImportError: # This is handled in azure_rm_common @@ -565,8 +595,8 @@ ip_configuration_spec = dict( private_ip_allocation_method=dict(type='str', choices=['Dynamic', 'Static'], default='Dynamic'), public_ip_address_name=dict(type='str', aliases=['public_ip_address', 'public_ip_name']), public_ip_allocation_method=dict(type='str', choices=['Dynamic', 'Static'], default='Dynamic'), - load_balancer_backend_address_pools=dict(type='list'), - application_gateway_backend_address_pools=dict(type='list'), + load_balancer_backend_address_pools=dict(type='list', elements='raw'), + application_gateway_backend_address_pools=dict(type='list', elements='raw'), primary=dict(type='bool', default=False), application_security_groups=dict(type='list', elements='raw') ) @@ -591,11 +621,11 @@ class AzureRMNetworkInterface(AzureRMModuleBase): subnet_name=dict(type='str', aliases=['subnet']), virtual_network=dict(type='raw', aliases=['virtual_network_name']), public_ip_allocation_method=dict(type='str', choices=['Dynamic', 'Static'], default='Dynamic'), - ip_configurations=dict(type='list', default=None, elements='dict', options=ip_configuration_spec), + ip_configurations=dict(type='list', default=[], elements='dict', options=ip_configuration_spec), os_type=dict(type='str', choices=['Windows', 'Linux'], default='Linux'), - open_ports=dict(type='list'), + open_ports=dict(type='list', elements='str'), enable_ip_forwarding=dict(type='bool', aliases=['ip_forwarding'], default=False), - dns_servers=dict(type='list'), + dns_servers=dict(type='list', elements='str'), ) required_if = [ diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_networkinterface_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_networkinterface_info.py index 10b55c6fc..deeb2c8c6 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_networkinterface_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_networkinterface_info.py @@ -24,9 +24,11 @@ options: name: description: - Only show results for a specific network interface. + type: str resource_group: description: - Name of the resource group containing the network interface(s). Required when searching by name. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -43,21 +45,21 @@ author: ''' EXAMPLES = ''' - - name: Get facts for one network interface - azure_rm_networkinterface_info: - resource_group: myResourceGroup - name: nic001 - - - name: Get network interfaces within a resource group - azure_rm_networkinterface_info: - resource_group: myResourceGroup - - - name: Get network interfaces by tag - azure_rm_networkinterface_info: - resource_group: myResourceGroup - tags: - - testing - - foo:bar +- name: Get facts for one network interface + azure_rm_networkinterface_info: + resource_group: myResourceGroup + name: nic001 + +- name: Get network interfaces within a resource group + azure_rm_networkinterface_info: + resource_group: myResourceGroup + +- name: Get network interfaces by tag + azure_rm_networkinterface_info: + resource_group: myResourceGroup + tags: + - testing + - foo:bar ''' RETURN = ''' @@ -111,61 +113,79 @@ networkinterfaces: id: description: - Id of the network interface. + type: str resource_group: description: - Name of a resource group where the network interface exists. + type: str name: description: - Name of the network interface. + type: str location: description: - Azure location. + type: str virtual_network: description: - An existing virtual network with which the network interface will be associated. - It is a dict which contains I(name) and I(resource_group) of the virtual network. + type: raw subnet: description: - Name of an existing subnet within the specified virtual network. + type: str tags: description: - Tags of the network interface. + type: dict ip_configurations: description: - List of IP configurations, if contains multiple configurations. + type: complex contains: name: description: - Name of the IP configuration. + type: str private_ip_address: description: - Private IP address for the IP configuration. + type: list private_ip_allocation_method: description: - Private IP allocation method. + type: str public_ip_address: description: - Name of the public IP address. None for disable IP address. + type: str public_ip_allocation_method: description: - Public IP allocation method. + type: str load_balancer_backend_address_pools: description: - List of existing load-balancer backend address pools associated with the network interface. + type: list application_gateway_backend_address_pools: description: - List of existing application gateway backend address pools associated with the network interface. version_added: "1.10.0" + type: list primary: description: - Whether the IP configuration is the primary one in the list. + type: bool application_security_groups: description: - List of Application security groups. - sample: /subscriptions/<subsid>/resourceGroups/<rg>/providers/Microsoft.Network/applicationSecurityGroups/myASG + type: list + sample: ['/subscriptions/<subsid>/resourceGroups/<rg>/providers/Microsoft.Network/applicationSecurityGroups/myASG'] enable_accelerated_networking: description: - Specifies whether the network interface should be created with the accelerated networking feature or not. + type: bool create_with_security_group: description: - Specifies whether a default security group should be be created with the NIC. Only applies when creating a new NIC. @@ -173,40 +193,49 @@ networkinterfaces: security_group: description: - A security group resource ID with which to associate the network interface. + type: str enable_ip_forwarding: description: - Whether to enable IP forwarding + type: bool dns_servers: description: - Which DNS servers should the NIC lookup. - List of IP addresses. + type: list mac_address: description: - The MAC address of the network interface. + type: str provisioning_state: description: - The provisioning state of the network interface. + type: str dns_settings: description: - The DNS settings in network interface. + type: complex contains: dns_servers: description: - List of DNS servers IP addresses. + type: list applied_dns_servers: description: - If the VM that uses this NIC is part of an Availability Set, then this list will have the union of all DNS servers from all NICs that are part of the Availability Set. This property is what is configured on each of those VMs. + type: list internal_dns_name_label: description: - Relative DNS name for this NIC used for internal communications between VMs in the same virtual network. + type: str internal_fqdn: description: - Fully qualified DNS name supporting internal communications between VMs in the same virtual network. + type: str ''' # NOQA try: from azure.core.exceptions import ResourceNotFoundError - from azure.common import AzureMissingResourceHttpError, AzureHttpError except Exception: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_notificationhub.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_notificationhub.py index 53c07cc81..dca1f0dfa 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_notificationhub.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_notificationhub.py @@ -68,7 +68,7 @@ EXAMPLES = ''' namespace_name: myNamespace name: myhub tags: - - a: b + - a: b sku: free - name: Delete Notification Hub @@ -83,7 +83,7 @@ EXAMPLES = ''' location: eastus namespace_name: myNamespace tags: - - a: b + - a: b sku: free - name: Delete Notification Hub Namespace @@ -91,7 +91,6 @@ EXAMPLES = ''' resource_group: testgroupans namespace_name: myNamespace state: absent - ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_notificationhub_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_notificationhub_info.py index 5ab211c6d..b3635768d 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_notificationhub_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_notificationhub_info.py @@ -41,11 +41,10 @@ author: EXAMPLES = ''' - - name: Get facts of specific notification hub - community.azure.azure_rm_notificationhub_info: - resource_group: myResourceGroup - name: myNotificationHub - +- name: Get facts of specific notification hub + community.azure.azure_rm_notificationhub_info: + resource_group: myResourceGroup + name: myNotificationHub ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedcluster.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedcluster.py index cffee5ceb..cc579c998 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedcluster.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedcluster.py @@ -41,7 +41,6 @@ options: description: - Pull secret for the cluster (immutable). type: str - default: "" domain: description: - The domain for the cluster (immutable). @@ -105,6 +104,7 @@ options: description: - Configuration for OpenShift worker Vms. type: list + elements: dict suboptions: name: description: name of the worker profile (immutable). @@ -157,6 +157,7 @@ options: description: - Ingress profiles configuration. only one profile is supported at the current API version. type: list + elements: dict suboptions: visibility: description: @@ -198,34 +199,34 @@ author: ''' EXAMPLES = ''' - - name: Create openshift cluster - azure_rm_openshiftmanagedcluster: - resource_group: "myResourceGroup" - name: "myCluster" - location: "eastus" - cluster_profile: - cluster_resource_group_id: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/clusterResourceGroup" - domain: "mydomain" - service_principal_profile: - client_id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" - client_secret: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - network_profile: - pod_cidr: "10.128.0.0/14" - service_cidr: "172.30.0.0/16" - worker_profiles: - - vm_size : "Standard_D4s_v3" - subnet_id : "/subscriptions/xx-xx-xx-xx-xx/resourceGroups/myResourceGroup/Microsoft.Network/virtualNetworks/myVnet/subnets/worker" - disk_size : 128 - count : 3 - master_profile: - vm_size : "Standard_D8s_v3" - subnet_id: "/subscriptions/xx-xx-xx-xx-xx/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVnet/subnets/master" - - name: Delete OpenShift Managed Cluster - azure_rm_openshiftmanagedcluster: - resource_group: myResourceGroup - name: myCluster - location: eastus - state: absent +- name: Create openshift cluster + azure_rm_openshiftmanagedcluster: + resource_group: "myResourceGroup" + name: "myCluster" + location: "eastus" + cluster_profile: + cluster_resource_group_id: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/clusterResourceGroup" + domain: "mydomain" + service_principal_profile: + client_id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + client_secret: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + network_profile: + pod_cidr: "10.128.0.0/14" + service_cidr: "172.30.0.0/16" + worker_profiles: + - vm_size: "Standard_D4s_v3" + subnet_id: "/subscriptions/xx-xx-xx-xx-xx/resourceGroups/myResourceGroup/Microsoft.Network/virtualNetworks/myVnet/subnets/worker" + disk_size: 128 + count: 3 + master_profile: + vm_size: "Standard_D8s_v3" + subnet_id: "/subscriptions/xx-xx-xx-xx-xx/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVnet/subnets/master" +- name: Delete OpenShift Managed Cluster + azure_rm_openshiftmanagedcluster: + resource_group: myResourceGroup + name: myCluster + location: eastus + state: absent ''' RETURN = ''' @@ -400,11 +401,6 @@ import json import random 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 -try: - from msrestazure.azure_exceptions import CloudError -except ImportError: - # this is handled in azure_rm_common - pass class Actions: @@ -526,6 +522,7 @@ class AzureRMOpenShiftManagedClusters(AzureRMModuleBaseExt): ), worker_profiles=dict( type='list', + elements='dict', disposition='/properties/workerProfiles', options=dict( name=dict( @@ -587,6 +584,7 @@ class AzureRMOpenShiftManagedClusters(AzureRMModuleBaseExt): ), ingress_profiles=dict( type='list', + elements='dict', disposition='/properties/ingressProfiles', options=dict( name=dict( @@ -653,6 +651,7 @@ class AzureRMOpenShiftManagedClusters(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) self.url = ('/subscriptions' + @@ -753,14 +752,14 @@ class AzureRMOpenShiftManagedClusters(AzureRMModuleBaseExt): self.status_code, 600, 30) - except CloudError as exc: + except Exception as exc: self.log('Error attempting to create the OpenShiftManagedCluster instance.') self.fail('Error creating the OpenShiftManagedCluster instance: {0}' '\n{1}'.format(str(self.body), str(exc))) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: - response = {'text': response.text} + response = {'text': response.context['deserialized_data']} pass return response @@ -776,7 +775,7 @@ class AzureRMOpenShiftManagedClusters(AzureRMModuleBaseExt): self.status_code, 600, 30) - except CloudError as e: + except Exception as e: self.log('Error attempting to delete the OpenShiftManagedCluster instance.') self.fail('Error deleting the OpenShiftManagedCluster instance: {0}'.format(str(e))) @@ -795,11 +794,11 @@ class AzureRMOpenShiftManagedClusters(AzureRMModuleBaseExt): 600, 30) found = True - response = json.loads(response.text) + response = json.loads(response.body()) found = True self.log("Response : {0}".format(response)) # self.log("OpenShiftManagedCluster instance : {0} found".format(response.name)) - except CloudError as e: + except Exception as e: self.log('Did not find the OpenShiftManagedCluster instance.') if found is True: return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedcluster_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedcluster_info.py index 0070bd0d3..ed359c641 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedcluster_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedcluster_info.py @@ -211,16 +211,9 @@ properties: sample: Public ''' -import time import json -import random 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 -try: - from msrestazure.azure_exceptions import CloudError -except ImportError: - # this is handled in azure_rm_common - pass class Actions: @@ -261,6 +254,7 @@ class AzureRMOpenShiftManagedClustersInfo(AzureRMModuleBaseExt): setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if (self.resource_group is not None and self.name is not None): @@ -296,9 +290,9 @@ class AzureRMOpenShiftManagedClustersInfo(AzureRMModuleBaseExt): self.status_code, 600, 30) - results = json.loads(response.text) + results = json.loads(response.body()) # self.log('Response : {0}'.format(response)) - except CloudError as e: + except Exception as e: self.log('Could not get info for @(Model.ModuleOperationNameUpper).') return {} @@ -327,9 +321,9 @@ class AzureRMOpenShiftManagedClustersInfo(AzureRMModuleBaseExt): self.status_code, 600, 30) - results = json.loads(response.text) + results = json.loads(response.body()) # self.log('Response : {0}'.format(response)) - except CloudError as e: + except Exception as e: self.log('Could not get info for @(Model.ModuleOperationNameUpper).') return [self.format_item(x) for x in results['value']] if results['value'] else [] @@ -354,9 +348,9 @@ class AzureRMOpenShiftManagedClustersInfo(AzureRMModuleBaseExt): self.status_code, 600, 30) - results = json.loads(response.text) + results = json.loads(response.body()) # self.log('Response : {0}'.format(response)) - except CloudError as e: + except Exception as e: self.log('Could not get info for @(Model.ModuleOperationNameUpper).') return results # return [self.format_item(x) for x in results['value']] if results['value'] else [] diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlconfiguration.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlconfiguration.py index 4d95b5b71..65d3bf060 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlconfiguration.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlconfiguration.py @@ -21,21 +21,26 @@ options: description: - The name of the resource group that contains the resource. required: True + type: str server_name: description: - The name of the server. required: True + type: str name: description: - Setting name. required: True + type: str value: description: - Setting value. + type: str state: description: - Assert the state of the PostgreSQL setting. Use C(present) to update setting, or C(absent) to reset to default value. default: present + type: str choices: - absent - present @@ -49,12 +54,12 @@ author: ''' EXAMPLES = ''' - - name: Update PostgreSQL Server setting - azure_rm_postgresqlconfiguration: - resource_group: myResourceGroup - server_name: myServer - name: deadlock_timeout - value: 2000 +- name: Update PostgreSQL Server setting + azure_rm_postgresqlconfiguration: + resource_group: myResourceGroup + server_name: myServer + name: deadlock_timeout + value: 2000 ''' RETURN = ''' @@ -67,11 +72,8 @@ id: gurations/event_scheduler" ''' -import time - try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase - from msrest.serialization import Model from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller except ImportError: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlconfiguration_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlconfiguration_info.py index 38a97cccb..38f3a9f42 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlconfiguration_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlconfiguration_info.py @@ -41,16 +41,16 @@ author: ''' EXAMPLES = ''' - - name: Get specific setting of PostgreSQL configuration - azure_rm_postgresqlconfiguration_info: - resource_group: myResourceGroup - server_name: testpostgresqlserver - name: deadlock_timeout - - - name: Get all settings of PostgreSQL Configuration - azure_rm_postgresqlconfiguration_info: - resource_group: myResourceGroup - server_name: testpostgresqlserver +- name: Get specific setting of PostgreSQL configuration + azure_rm_postgresqlconfiguration_info: + resource_group: myResourceGroup + server_name: testpostgresqlserver + name: deadlock_timeout + +- name: Get all settings of PostgreSQL Configuration + azure_rm_postgresqlconfiguration_info: + resource_group: myResourceGroup + server_name: testpostgresqlserver ''' RETURN = ''' @@ -96,8 +96,6 @@ settings: try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError - from msrestazure.azure_operation import AzureOperationPoller - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqldatabase.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqldatabase.py index 4c54e6db7..78520e94a 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqldatabase.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqldatabase.py @@ -21,22 +21,27 @@ options: description: - The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal. required: True + type: str server_name: description: - The name of the server. required: True + type: str name: description: - The name of the database. required: True + type: str charset: description: - The charset of the database. Check PostgreSQL documentation for possible values. - This is only set on creation, use I(force_update) to recreate a database if the values don't match. + type: str collation: description: - The collation of the database. Check PostgreSQL documentation for possible values. - This is only set on creation, use I(force_update) to recreate a database if the values don't match. + type: str force_update: description: - When set to C(true), will delete and recreate the existing PostgreSQL database if any of the properties don't match what is set. @@ -47,6 +52,7 @@ options: description: - Assert the state of the PostgreSQL database. Use C(present) to create or update a database and C(absent) to delete it. default: present + type: str choices: - absent - present @@ -60,11 +66,11 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) PostgreSQL Database - azure_rm_postgresqldatabase: - resource_group: myResourceGroup - server_name: testserver - name: db1 +- name: Create (or update) PostgreSQL Database + azure_rm_postgresqldatabase: + resource_group: myResourceGroup + server_name: testserver + name: db1 ''' RETURN = ''' @@ -87,10 +93,8 @@ import time try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase - from azure.mgmt.rdbms.postgresql import PostgreSQLManagementClient from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqldatabase_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqldatabase_info.py index d70fbd54b..471344e64 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqldatabase_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqldatabase_info.py @@ -41,16 +41,16 @@ author: ''' EXAMPLES = ''' - - name: Get instance of PostgreSQL Database - azure_rm_postgresqldatabase_info: - resource_group: myResourceGroup - server_name: server_name - name: database_name - - - name: List instances of PostgreSQL Database - azure_rm_postgresqldatabase_info: - resource_group: myResourceGroup - server_name: server_name +- name: Get instance of PostgreSQL Database + azure_rm_postgresqldatabase_info: + resource_group: myResourceGroup + server_name: server_name + name: database_name + +- name: List instances of PostgreSQL Database + azure_rm_postgresqldatabase_info: + resource_group: myResourceGroup + server_name: server_name ''' RETURN = ''' @@ -102,7 +102,6 @@ databases: try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlfirewallrule.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlfirewallrule.py index 4eb702e19..54de3ce6b 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlfirewallrule.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlfirewallrule.py @@ -21,23 +21,29 @@ options: description: - The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal. required: True + type: str server_name: description: - The name of the server. required: True + type: str name: description: - The name of the PostgreSQL firewall rule. required: True + type: str start_ip_address: description: - The start IP address of the PostgreSQL firewall rule. Must be IPv4 format. + type: str end_ip_address: description: - The end IP address of the PostgreSQL firewall rule. Must be IPv4 format. + type: str state: description: - Assert the state of the PostgreSQL firewall rule. Use C(present) to create or update a PostgreSQL firewall rule and C(absent) to delete it. + type: str default: present choices: - absent @@ -52,13 +58,13 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) PostgreSQL firewall rule - azure_rm_postgresqlfirewallrule: - resource_group: myResourceGroup - server_name: testserver - name: rule1 - start_ip_address: 10.0.0.16 - end_ip_address: 10.0.0.18 +- name: Create (or update) PostgreSQL firewall rule + azure_rm_postgresqlfirewallrule: + resource_group: myResourceGroup + server_name: testserver + name: rule1 + start_ip_address: 10.0.0.16 + end_ip_address: 10.0.0.18 ''' RETURN = ''' @@ -77,7 +83,6 @@ try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlfirewallrule_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlfirewallrule_info.py index 578fe6576..e2dc889df 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlfirewallrule_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlfirewallrule_info.py @@ -41,16 +41,16 @@ author: ''' EXAMPLES = ''' - - name: Get instance of PostgreSQL Firewall Rule - azure_rm_postgresqlfirewallrule_info: - resource_group: myResourceGroup - server_name: server_name - name: firewall_rule_name - - - name: List instances of PostgreSQL Firewall Rule - azure_rm_postgresqlfirewallrule_info: - resource_group: myResourceGroup - server_name: server_name +- name: Get instance of PostgreSQL Firewall Rule + azure_rm_postgresqlfirewallrule_info: + resource_group: myResourceGroup + server_name: server_name + name: firewall_rule_name + +- name: List instances of PostgreSQL Firewall Rule + azure_rm_postgresqlfirewallrule_info: + resource_group: myResourceGroup + server_name: server_name ''' RETURN = ''' @@ -96,7 +96,6 @@ rules: try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlserver.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlserver.py index 524050565..ab9022905 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlserver.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlserver.py @@ -128,19 +128,19 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) PostgreSQL Server - azure_rm_postgresqlserver: - resource_group: myResourceGroup - name: testserver - sku: - name: B_Gen5_1 - tier: Basic - location: eastus - storage_mb: 1024 - enforce_ssl: True - storage_autogrow: True - admin_username: cloudsa - admin_password: password +- name: Create (or update) PostgreSQL Server + azure_rm_postgresqlserver: + resource_group: myResourceGroup + name: testserver + sku: + name: B_Gen5_1 + tier: Basic + location: eastus + storage_mb: 1024 + enforce_ssl: true + storage_autogrow: true + admin_username: cloudsa + admin_password: password ''' RETURN = ''' @@ -176,7 +176,6 @@ try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlserver_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlserver_info.py index 159148e34..04f5edf82 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlserver_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlserver_info.py @@ -41,16 +41,16 @@ author: ''' EXAMPLES = ''' - - name: Get instance of PostgreSQL Server - azure_rm_postgresqlserver_info: - resource_group: myResourceGroup - name: server_name +- name: Get instance of PostgreSQL Server + azure_rm_postgresqlserver_info: + resource_group: myResourceGroup + name: server_name - - name: List instances of PostgreSQL Server - azure_rm_postgresqlserver_info: - resource_group: myResourceGroup - tags: - - key +- name: List instances of PostgreSQL Server + azure_rm_postgresqlserver_info: + resource_group: myResourceGroup + tags: + - key ''' RETURN = ''' @@ -168,7 +168,6 @@ servers: try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednsrecordset.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednsrecordset.py index ca998d1ff..3560139e7 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednsrecordset.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednsrecordset.py @@ -133,9 +133,9 @@ EXAMPLES = ''' record_type: "{{ item.type }}" records: "{{ item.records }}" with_items: - - { name: 'servera', type: 'A', records: [ { entry: '10.10.10.20' }, { entry: '10.10.10.21' }] } - - { name: 'serverb', type: 'A', records: [ { entry: '10.10.10.30' }, { entry: '10.10.10.41' }] } - - { name: 'serverc', type: 'A', records: [ { entry: '10.10.10.40' }, { entry: '10.10.10.41' }] } + - {name: 'servera', type: 'A', records: [{ entry: '10.10.10.20'}, {entry: '10.10.10.21'}]} + - {name: 'serverb', type: 'A', records: [{ entry: '10.10.10.30'}, {entry: '10.10.10.41'}]} + - {name: 'serverc', type: 'A', records: [{ entry: '10.10.10.40'}, {entry: '10.10.10.41'}]} - name: create SRV records in a new record set azure_rm_privatednsrecordset: @@ -145,10 +145,10 @@ EXAMPLES = ''' time_to_live: 7200 record_type: SRV records: - - entry: sip.testing.com - priority: 20 - weight: 10 - port: 5060 + - entry: sip.testing.com + priority: 20 + weight: 10 + port: 5060 - name: create PTR record in a new record set azure_rm_privatednsrecordset: @@ -157,7 +157,7 @@ EXAMPLES = ''' zone_name: testing.com record_type: PTR records: - - entry: servera.testing.com + - entry: servera.testing.com - name: create TXT record in a new record set azure_rm_privatednsrecordset: @@ -166,7 +166,7 @@ EXAMPLES = ''' zone_name: testing.com record_type: TXT records: - - entry: 'v=spf1 a -all' + - entry: 'v=spf1 a -all' - name: Update SOA record azure_rm_privatednsrecordset: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednszone.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednszone.py index 4a84cdbce..0dfa133e9 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednszone.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednszone.py @@ -61,7 +61,6 @@ EXAMPLES = ''' resource_group: myResourceGroup name: example.com state: absent - ''' RETURN = ''' @@ -81,8 +80,7 @@ state: ''' -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, format_resource_id -from ansible.module_utils._text import to_native +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: from azure.core.exceptions import ResourceNotFoundError diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednszone_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednszone_info.py index 5a5730e4c..3b5cbbca0 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednszone_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednszone_info.py @@ -111,7 +111,6 @@ privatednszones: ''' from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase -from ansible.module_utils._text import to_native try: from azure.core.exceptions import ResourceNotFoundError diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednszonelink.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednszonelink.py index b87b54a6b..65168ea6b 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednszonelink.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednszonelink.py @@ -156,7 +156,7 @@ state: ''' from ansible.module_utils.basic import _load_params -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, HAS_AZURE, \ +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, \ format_resource_id try: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privateendpoint_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privateendpoint_info.py index dbf39e969..bddf2a098 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privateendpoint_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privateendpoint_info.py @@ -42,19 +42,19 @@ author: ''' EXAMPLES = ''' - - name: Get facts for one private endpoint - azure_rm_privateendpoint_info: - resource_group: myResourceGroup - name: testprivateendpoint +- name: Get facts for one private endpoint + azure_rm_privateendpoint_info: + resource_group: myResourceGroup + name: testprivateendpoint - - name: Get all private endpoint under the resource group - azure_rm_privateendpoint_info: - resource_group: myResourceGroup +- name: Get all private endpoint under the resource group + azure_rm_privateendpoint_info: + resource_group: myResourceGroup - - name: Get all private endpoint under subscription - azure_rm_virtualnetwork_info: - tags: - - key1:value1 +- name: Get all private endpoint under subscription + azure_rm_virtualnetwork_info: + tags: + - key1:value1 ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privateendpointdnszonegroup.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privateendpointdnszonegroup.py index 1d5480de3..7c2af8402 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privateendpointdnszonegroup.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privateendpointdnszonegroup.py @@ -182,7 +182,7 @@ state: ''' try: - from msrestazure.tools import resource_id + from azure.mgmt.core.tools import resource_id from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller except ImportError: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatelinkservice.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatelinkservice.py index 611adb161..a87302b1c 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatelinkservice.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatelinkservice.py @@ -141,7 +141,7 @@ EXAMPLES = ''' azure_rm_privatelinkservice: name: linkservice-name resource_group: myResourceGroup - enable_proxy_protocol: True + enable_proxy_protocol: true fqdns: - 'dns01.com' - 'dns02.com' @@ -154,18 +154,18 @@ EXAMPLES = ''' - xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - yyyyyy-yyyyy-yyyy-yyyy-yyyyyyyyyyy load_balancer_frontend_ip_configurations: - - id: load_balancer_frontend_ip_configurations_id + - id: load_balancer_frontend_ip_configurations_id ip_configurations: - name: testSubnet properties: - primary: False + primary: false private_ip_allocation_method: 'Dynamic' private_ip_address_version: 'IPv4' subnet: id: subnet_id - name: subnetfredprivate-1 properties: - primary: True + primary: true private_ip_allocation_method: 'Static' private_ip_address_version: 'IPv4' subnet: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_proximityplacementgroup.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_proximityplacementgroup.py index da68e776e..7852c1dcf 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_proximityplacementgroup.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_proximityplacementgroup.py @@ -121,8 +121,7 @@ state: ''' from ansible.module_utils.basic import _load_params -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, HAS_AZURE, \ - format_resource_id, normalize_location_name +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, normalize_location_name try: from azure.core.exceptions import ResourceNotFoundError diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_publicipaddress.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_publicipaddress.py index 45fc9c807..4d6cf341c 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_publicipaddress.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_publicipaddress.py @@ -27,10 +27,12 @@ options: description: - Name of resource group with which the Public IP is associated. required: true + type: str allocation_method: description: - Control whether the assigned Public IP remains permanently assigned to the object. - If not set to C(Static), the IP address may changed anytime an associated virtual machine is power cycled. + type: str choices: - dynamic - static @@ -41,27 +43,32 @@ options: description: - The customizable portion of the FQDN assigned to public IP address. This is an explicit setting. - If no value is provided, any existing value will be removed on an existing public IP. + type: str aliases: - domain_name_label name: description: - Name of the Public IP. + type: str required: true state: description: - Assert the state of the Public IP. Use C(present) to create or update a and C(absent) to delete. default: present + type: str choices: - absent - present location: description: - Valid Azure location. Defaults to location of the resource group. + type: str sku: description: - The public IP address SKU. - When I(version=ipv6), if I(sku=standard) then set I(allocation_method=static). - When I(version=ipv4), if I(sku=standard) then set I(allocation_method=static). + type: str choices: - basic - standard @@ -71,13 +78,19 @@ options: description: - List of IpTag associated with the public IP address. - Each element should contain type:value pair. + type: list + elements: dict suboptions: type: description: - Sets the ip_tags type. + type: str + required: true value: description: - Sets the ip_tags value. + type: str + required: true idle_timeout: description: - Idle timeout in minutes. @@ -85,6 +98,7 @@ options: version: description: - The public IP address version. + type: str choices: - ipv4 - ipv6 @@ -109,18 +123,18 @@ author: ''' EXAMPLES = ''' - - name: Create a public ip address - azure_rm_publicipaddress: - resource_group: myResourceGroup - name: my_public_ip - allocation_method: static - domain_name: foobar - - - name: Delete public ip - azure_rm_publicipaddress: - resource_group: myResourceGroup - name: my_public_ip - state: absent +- name: Create a public ip address + azure_rm_publicipaddress: + resource_group: myResourceGroup + name: my_public_ip + allocation_method: static + domain_name: foobar + +- name: Delete public ip + azure_rm_publicipaddress: + resource_group: myResourceGroup + name: my_public_ip + state: absent ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_publicipaddress_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_publicipaddress_info.py index 63c670529..0c2798c7b 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_publicipaddress_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_publicipaddress_info.py @@ -24,9 +24,11 @@ options: name: description: - Only show results for a specific Public IP. + type: str resource_group: description: - Limit results by resource group. Required when using name parameter. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -42,16 +44,16 @@ author: ''' EXAMPLES = ''' - - name: Get facts for one Public IP - azure_rm_publicipaddress_info: - resource_group: myResourceGroup - name: publicip001 - - - name: Get facts for all Public IPs within a resource groups - azure_rm_publicipaddress_info: - resource_group: myResourceGroup - tags: - - key:value +- name: Get facts for one Public IP + azure_rm_publicipaddress_info: + resource_group: myResourceGroup + name: publicip001 + +- name: Get facts for all Public IPs within a resource groups + azure_rm_publicipaddress_info: + resource_group: myResourceGroup + tags: + - key:value ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_recoveryservicesvault.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_recoveryservicesvault.py index d793e75bd..b2c45b2d5 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_recoveryservicesvault.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_recoveryservicesvault.py @@ -49,18 +49,18 @@ author: ''' EXAMPLES = ''' - - name: Create/Update Azure Recovery Service vault - azure_rm_recoveryservicesvault: - resource_group: 'myResourceGroup' - name: 'testVault' - location: 'westeurope' - state: 'present' - - name: Delete Recovery Service Vault - azure_rm_recoveryservicesvault: - resource_group: 'myResourceGroup' - name: 'testVault' - location: 'westeurope' - state: 'absent' +- name: Create/Update Azure Recovery Service vault + azure_rm_recoveryservicesvault: + resource_group: 'myResourceGroup' + name: 'testVault' + location: 'westeurope' + state: 'present' +- name: Delete Recovery Service Vault + azure_rm_recoveryservicesvault: + resource_group: 'myResourceGroup' + name: 'testVault' + location: 'westeurope' + state: 'absent' ''' RETURN = ''' @@ -121,9 +121,7 @@ response: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_rest import GenericRestClient from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt -import re import json -import time class AzureRMRecoveryServicesVault(AzureRMModuleBaseExt): @@ -210,6 +208,7 @@ class AzureRMRecoveryServicesVault(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) old_response = self.get_resource() @@ -249,9 +248,9 @@ class AzureRMRecoveryServicesVault(AzureRMModuleBaseExt): self.fail('Error in creating Azure Recovery Service Vault {0}'.format(str(e))) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: - response = {'text': response.text} + response = {'text': response.context['deserialized_data']} return response @@ -272,12 +271,6 @@ class AzureRMRecoveryServicesVault(AzureRMModuleBaseExt): self.log('Error attempting to delete Azure Recovery Service Vault.') self.fail('Error while deleting Azure Recovery Service Vault: {0}'.format(str(e))) - try: - response = json.loads(response.text) - except Exception: - response = {'text': response.text} - return response - def get_resource(self): # self.log('Get Recovery Service Vault Name {0}'.format(self.)) found = False @@ -296,7 +289,7 @@ class AzureRMRecoveryServicesVault(AzureRMModuleBaseExt): except Exception as e: self.log('Recovery Service Vault Does not exist.') if found is True: - response = json.loads(response.text) + response = json.loads(response.body()) return response else: return False diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_recoveryservicesvault_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_recoveryservicesvault_info.py index e7f2a6192..6b2dee776 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_recoveryservicesvault_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_recoveryservicesvault_info.py @@ -34,10 +34,10 @@ author: ''' EXAMPLES = ''' - - name: Get Azure Recovery Services Vault Details. - azure_rm_recoveryservicesvault_info: - resource_group: 'myResourceGroup' - name: 'testVault' +- name: Get Azure Recovery Services Vault Details. + azure_rm_recoveryservicesvault_info: + resource_group: 'myResourceGroup' + name: 'testVault' ''' RETURN = ''' @@ -98,9 +98,7 @@ response: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_rest import GenericRestClient from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt -import re import json -import time class AzureRMRecoveryServicesVaultInfo(AzureRMModuleBaseExt): @@ -162,6 +160,7 @@ class AzureRMRecoveryServicesVaultInfo(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) changed = True @@ -190,9 +189,9 @@ class AzureRMRecoveryServicesVaultInfo(AzureRMModuleBaseExt): self.fail('Error in fetching Azure Recovery Service Vault Details {0}'.format(str(e))) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: - response = {'text': response.text} + response = {'text': response.context['deserialized_data']} return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscache.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscache.py index e004eb056..b93a52992 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscache.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscache.py @@ -21,31 +21,39 @@ options: description: - Name of the resource group to which the resource belongs. required: True + type: str name: description: - Unique name of the Azure Cache for Redis to create or update. required: True + type: str location: description: - Resource location. If not set, location from the resource group will be used as default. + type: str sku: description: - SKU info of Azure Cache for Redis. + type: dict + required: true suboptions: name: description: - Type of Azure Cache for Redis to deploy. + type: str + required: true choices: - basic - standard - premium - required: True size: description: - Size of Azure Cache for Redis to deploy. - When I(sku=basic) or I(sku=standard), allowed values are C(C0), C(C1), C(C2), C(C3), C(C4), C(C5), C(C6). - When I(sku=premium), allowed values are C(P1), C(P2), C(P3), C(P4). - Please see U(https://docs.microsoft.com/en-us/rest/api/redis/redis/create#sku) for allowed values. + type: str + required: true choices: - C0 - C1 @@ -58,7 +66,6 @@ options: - P2 - P3 - P4 - required: True enable_non_ssl_port: description: - When set I(enable_non_ssl_port=true), the non-ssl Redis server port 6379 will be enabled. @@ -68,14 +75,17 @@ options: description: - Configures the amount of memory in MB that is reserved to accommodate for memory fragmentation. - Please see U(https://docs.microsoft.com/en-us/azure/redis-cache/cache-configure#advanced-settings) for more detail. + type: int maxmemory_reserved: description: - Configures the amount of memory in MB that is reserved for non-cache operations. - Please see U(https://docs.microsoft.com/en-us/azure/redis-cache/cache-configure#advanced-settings) for more detail. + type: int maxmemory_policy: description: - Configures the eviction policy of the cache. - Please see U(https://docs.microsoft.com/en-us/azure/redis-cache/cache-configure#advanced-settings) for more detail. + type: str choices: - volatile_lru - allkeys_lru @@ -122,6 +132,7 @@ options: static_ip: description: - Static IP address. Required when deploying an Azure Cache for Redis inside an existing Azure virtual network. + type: str subnet: description: - Subnet in a virtual network to deploy the Azure Cache for Redis in. @@ -131,6 +142,7 @@ options: - I(name). Name of the subnet. - I(resource_group). Resource group name of the subnet. - I(virtual_network_name). Name of virtual network to which this subnet belongs. + type: raw tenant_settings: description: - Dict of tenant settings. @@ -138,26 +150,29 @@ options: reboot: description: - Reboot specified Redis node(s). There can be potential data loss. + type: dict suboptions: shard_id: description: - If clustering is enabled, the id of the shard to be rebooted. - type: int + type: str reboot_type: description: - Which Redis node(s) to reboot. + type: str choices: - primary - secondary - all - default: all regenerate_key: description: - Regenerate Redis cache's access keys. + type: dict suboptions: key_type: description: - The Redis key to regenerate. + type: str choices: - primary - secondary @@ -170,13 +185,14 @@ options: type: bool default: True state: - description: - - Assert the state of the Azure Cache for Redis. - - Use C(present) to create or update an Azure Cache for Redis and C(absent) to delete it. - default: present - choices: - - absent - - present + description: + - Assert the state of the Azure Cache for Redis. + - Use C(present) to create or update an Azure Cache for Redis and C(absent) to delete it. + default: present + type: str + choices: + - absent + - present extends_documentation_fragment: - azure.azcollection.azure @@ -193,8 +209,8 @@ EXAMPLES = ''' resource_group: myResourceGroup name: myRedis sku: - name: basic - size: C1 + name: basic + size: C1 - name: Scale up the Azure Cache for Redis azure_rm_rediscache: @@ -251,7 +267,6 @@ import time try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.exceptions import ResourceNotFoundError - from msrestazure.azure_operation import AzureOperationPoller from azure.core.polling import LROPoller from azure.mgmt.redis import RedisManagementClient from azure.mgmt.redis.models import ( @@ -265,9 +280,11 @@ except ImportError: sku_spec = dict( name=dict( type='str', + required=True, choices=['basic', 'standard', 'premium']), size=dict( type='str', + required=True, choices=['C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'P1', 'P2', 'P3', 'P4'] ) ) @@ -362,6 +379,7 @@ class AzureRMRedisCaches(AzureRMModuleBase): ), sku=dict( type='dict', + required=True, options=sku_spec ), enable_non_ssl_port=dict( @@ -651,7 +669,7 @@ class AzureRMRedisCaches(AzureRMModuleBase): name=self.name, parameters=params) - if isinstance(response, AzureOperationPoller) or isinstance(response, LROPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) if self.wait_for_provisioning: @@ -692,7 +710,7 @@ class AzureRMRedisCaches(AzureRMModuleBase): response = self._client.redis.update(resource_group_name=self.resource_group, name=self.name, parameters=params) - if isinstance(response, AzureOperationPoller) or isinstance(response, LROPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) if self.wait_for_provisioning: @@ -758,7 +776,7 @@ class AzureRMRedisCaches(AzureRMModuleBase): response = self._client.redis.force_reboot(resource_group_name=self.resource_group, name=self.name, parameters=params) - if isinstance(response, AzureOperationPoller) or isinstance(response, LROPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) if self.wait_for_provisioning: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscache_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscache_info.py index fec05cd77..44e47f4d5 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscache_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscache_info.py @@ -24,9 +24,11 @@ options: description: - The resource group to search for the desired Azure Cache for Redis. required: True + type: str name: description: - Limit results to a specific Azure Cache for Redis. + type: str return_access_keys: description: - Indicate weather to return access keys of the Azure Cache for Redis. @@ -46,20 +48,20 @@ author: ''' EXAMPLES = ''' - - name: Get Azure Cache for Redis by name - azure_rm_rediscache_info: - resource_group: myResourceGroup - name: myRedis - - - name: Get Azure Cache for Redis with access keys by name - azure_rm_rediscache_info: - resource_group: myResourceGroup - name: myRedis - return_access_keys: true - - - name: Get Azure Cache for Redis in specific resource group - azure_rm_rediscache_info: - resource_group: myResourceGroup +- name: Get Azure Cache for Redis by name + azure_rm_rediscache_info: + resource_group: myResourceGroup + name: myRedis + +- name: Get Azure Cache for Redis with access keys by name + azure_rm_rediscache_info: + resource_group: myResourceGroup + name: myRedis + return_access_keys: true + +- name: Get Azure Cache for Redis in specific resource group + azure_rm_rediscache_info: + resource_group: myResourceGroup ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscachefirewallrule.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscachefirewallrule.py index 921f982a6..67b2c90b6 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscachefirewallrule.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscachefirewallrule.py @@ -21,30 +21,36 @@ options: description: - Name of the resource group to which the resource belongs. required: True + type: str cache_name: description: - Name of the Azure Cache for Redis. required: True + type: str name: description: - Name of the Firewall rule. required: True + type: str start_ip_address: description: - The start IP address of the Azure Cache for Redis Firewall rule. Must be IPv4 format. - Required when creating Firewall rule. + type: str end_ip_address: description: - The end IP address of the Azure Cache for Redis Firewall rule. Must be IPv4 format. - Required when creating Firewall rule. + type: str state: - description: - - Assert the state of the Firewall rule of Azure Cache for Redis. - - Use C(present) to create or update Firewall rule of Azure Cache for Redis and C(absent) to delete it. - default: present - choices: - - absent - - present + description: + - Assert the state of the Firewall rule of Azure Cache for Redis. + - Use C(present) to create or update Firewall rule of Azure Cache for Redis and C(absent) to delete it. + default: present + type: str + choices: + - absent + - present extends_documentation_fragment: - azure.azcollection.azure @@ -55,20 +61,20 @@ author: ''' EXAMPLES = ''' - - name: Create a Firewall rule for Azure Cache for Redis - azure_rm_rediscachefirewallrule: - resource_group: myResourceGroup - cache_name: myRedisCache - name: myRule - start_ip_address: 192.168.1.1 - end_ip_address: 192.168.1.4 - - - name: Update a Firewall rule for Azure Cache for Redis - azure_rm_rediscachefirewallrule: - resource_group: myResourceGroup - cache_name: myRedisCache - name: myRule - end_ip_address: 192.168.1.5 +- name: Create a Firewall rule for Azure Cache for Redis + azure_rm_rediscachefirewallrule: + resource_group: myResourceGroup + cache_name: myRedisCache + name: myRule + start_ip_address: 192.168.1.1 + end_ip_address: 192.168.1.4 + +- name: Update a Firewall rule for Azure Cache for Redis + azure_rm_rediscachefirewallrule: + resource_group: myResourceGroup + cache_name: myRedisCache + name: myRule + end_ip_address: 192.168.1.5 ''' RETURN = ''' @@ -80,12 +86,9 @@ id: sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Cache/redis/myRedis/firewallRules/myRule" ''' -import time - try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from azure.core.polling import LROPoller - from msrestazure.azure_operation import AzureOperationPoller from azure.core.exceptions import ResourceNotFoundError from azure.mgmt.redis import RedisManagementClient from azure.mgmt.redis.models import ( @@ -261,7 +264,7 @@ class AzureRMRedisCacheFirewallRule(AzureRMModuleBase): cache_name=self.cache_name, rule_name=self.name, parameters=params) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationassignment.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationassignment.py index b895d8883..a70542f80 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationassignment.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationassignment.py @@ -54,27 +54,26 @@ author: ''' EXAMPLES = ''' - - name: Delete Registration Assignment - azure_rm_registrationassignment: - scope: subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - registration_assignment_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - state: absent +- name: Delete Registration Assignment + azure_rm_registrationassignment: + scope: subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + registration_assignment_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + state: absent - - name: Create Registration Assignment in subscription level - azure_rm_registrationassignment: - scope: subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - registration_assignment_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - properties: - registration_definition_id: /subscriptions/xxx-xxx/providers/Microsoft.ManagedServices/registrationDefinitions/xxx-xxx +- name: Create Registration Assignment in subscription level + azure_rm_registrationassignment: + scope: subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + registration_assignment_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + properties: + registration_definition_id: /subscriptions/xxx-xxx/providers/Microsoft.ManagedServices/registrationDefinitions/xxx-xxx - - name: Create Registration Assignment in resourcegroup level with randomly generating registration_assignment_id - azure_rm_registrationassignment: - scope: subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup - properties: - registration_definition_id: /subscriptions/xxx-xxx/providers/Microsoft.ManagedServices/registrationDefinitions/xxx-xxx - +- name: Create Registration Assignment in resourcegroup level with randomly generating registration_assignment_id + azure_rm_registrationassignment: + scope: subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup + properties: + registration_definition_id: /subscriptions/xxx-xxx/providers/Microsoft.ManagedServices/registrationDefinitions/xxx-xxx ''' RETURN = ''' @@ -120,7 +119,6 @@ import uuid from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt try: from azure.mgmt.managedservices import ManagedServicesClient - from msrestazure.azure_operation import AzureOperationPoller from azure.core.polling import LROPoller except ImportError: # This is handled in azure_rm_common @@ -238,7 +236,7 @@ class AzureRMRegistrationAssignment(AzureRMModuleBaseExt): response = self.mgmt_client.registration_assignments.begin_create_or_update(scope=self.scope, registration_assignment_id=self.registration_assignment_id, request_body=self.body) - if isinstance(response, AzureOperationPoller) or isinstance(response, LROPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: self.log('Error attempting to create the RegistrationAssignment instance.') diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationassignment_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationassignment_info.py index 60003a192..ef8875f7c 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationassignment_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationassignment_info.py @@ -34,17 +34,15 @@ author: ''' EXAMPLES = ''' - - name: Get Registration Assignment - azure_rm_registrationassignment_info: - registration_assignment_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - scope: subscription/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup - - - - name: Get All Registration Assignments in scope(subscription) - azure_rm_registrationassignment_info: - scope: subscription/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +- name: Get Registration Assignment + azure_rm_registrationassignment_info: + registration_assignment_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + scope: subscription/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup +- name: Get All Registration Assignments in scope(subscription) + azure_rm_registrationassignment_info: + scope: subscription/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ''' RETURN = ''' @@ -89,10 +87,7 @@ registration_assignments: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBase try: - from msrestazure.azure_exceptions import CloudError from azure.mgmt.managedservices import ManagedServicesClient - from msrestazure.azure_operation import AzureOperationPoller - from msrest.polling import LROPoller except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationdefinition.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationdefinition.py index 9daaf9980..0d89da3a9 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationdefinition.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationdefinition.py @@ -106,34 +106,33 @@ author: ''' EXAMPLES = ''' - - name: Create Registration Definition without scope - azure_rm_registrationdefinition: - registration_definition_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - properties: - description: test - authorizations: - - principal_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - role_definition_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - managed_by_tenant_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - registration_definition_name: def4 - - - name: Create Registration Definition with scope - azure_rm_registrationdefinition: - scope: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - registration_definition_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - properties: - description: test - authorizations: - - principal_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - role_definition_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - managed_by_tenant_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - registration_definition_name: def5 - - - name: Delete Registration Definition - azure_rm_registrationdefinition: - registration_definition_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - state: absent - +- name: Create Registration Definition without scope + azure_rm_registrationdefinition: + registration_definition_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + properties: + description: test + authorizations: + - principal_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + role_definition_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + managed_by_tenant_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + registration_definition_name: def4 + +- name: Create Registration Definition with scope + azure_rm_registrationdefinition: + scope: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + registration_definition_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + properties: + description: test + authorizations: + - principal_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + role_definition_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + managed_by_tenant_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + registration_definition_name: def5 + +- name: Delete Registration Definition + azure_rm_registrationdefinition: + registration_definition_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + state: absent ''' RETURN = ''' @@ -241,7 +240,6 @@ import uuid from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt try: from azure.mgmt.managedservices import ManagedServicesClient - from msrestazure.azure_operation import AzureOperationPoller from azure.core.polling import LROPoller except ImportError: # This is handled in azure_rm_common @@ -411,7 +409,7 @@ class AzureRMRegistrationDefinition(AzureRMModuleBaseExt): scope=self.scope, request_body=self.body) - if isinstance(response, AzureOperationPoller) or isinstance(response, LROPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: self.log('Error attempting to create the RegistrationDefinition instance.') diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationdefinition_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationdefinition_info.py index 3c8fabe95..1c095420c 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationdefinition_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationdefinition_info.py @@ -33,17 +33,16 @@ author: ''' EXAMPLES = ''' - - name: Get Registration Definition - azure_rm_registrationdefinition_info: - registration_definition_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +- name: Get Registration Definition + azure_rm_registrationdefinition_info: + registration_definition_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - - name: Get All Registration Definitions from AzureRMAuth's subscription - azure_rm_registrationdefinition_info: - - - name: Get All Registration Definitions in the subscription levle - azure_rm_registrationdefinition_info: - scope: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +- name: Get All Registration Definitions from AzureRMAuth's subscription + azure_rm_registrationdefinition_info: +- name: Get All Registration Definitions in the subscription levle + azure_rm_registrationdefinition_info: + scope: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ''' RETURN = ''' @@ -149,10 +148,7 @@ registration_definitions: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBase try: - from msrestazure.azure_exceptions import CloudError from azure.mgmt.managedservices import ManagedServicesClient - from msrestazure.azure_operation import AzureOperationPoller - from msrest.polling import LROPoller except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resource.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resource.py index 0927128cd..a3a0544e2 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resource.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resource.py @@ -22,44 +22,58 @@ options: url: description: - Azure RM Resource URL. + type: str api_version: description: - Specific API version to be used. + type: str provider: description: - Provider type. - Required if URL is not specified. + type: str resource_group: description: - Resource group to be used. - Required if URL is not specified. + type: str resource_type: description: - Resource type. - Required if URL is not specified. + type: str resource_name: description: - Resource name. - Required if URL Is not specified. + type: str subresource: description: - List of subresources. + default: [] + type: list + elements: dict suboptions: namespace: description: - Subresource namespace. + type: str type: description: - Subresource type. + type: str name: description: - Subresource name. + type: str body: description: - The body of the HTTP request/response to the web service. + type: raw method: description: - The HTTP method of the request or response. It must be uppercase. + type: str choices: - GET - PUT @@ -73,11 +87,12 @@ options: description: - A valid, numeric, HTTP status code that signifies success of the request. Can also be comma separated list of status codes. type: list + elements: int default: [ 200, 201, 202 ] idempotency: description: - If enabled, idempotency check will be done by using I(method=GET) first and then comparing with I(body). - default: no + default: false type: bool polling_timeout: description: @@ -93,6 +108,7 @@ options: description: - Assert the state of the resource. Use C(present) to create or update resource or C(absent) to delete resource. default: present + type: str choices: - absent - present @@ -106,14 +122,14 @@ author: ''' EXAMPLES = ''' - - name: Update scaleset info using azure_rm_resource - azure_rm_resource: - resource_group: myResourceGroup - provider: compute - resource_type: virtualmachinescalesets - resource_name: myVmss - api_version: "2017-12-01" - body: { body } +- name: Update scaleset info using azure_rm_resource + azure_rm_resource: + resource_group: myResourceGroup + provider: compute + resource_type: virtualmachinescalesets + resource_name: myVmss + api_version: "2017-12-01" + body: { body } ''' RETURN = ''' @@ -215,9 +231,7 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common from ansible.module_utils.common.dict_transformations import dict_merge try: - from msrestazure.azure_exceptions import CloudError - from msrest.service_client import ServiceClient - from msrestazure.tools import resource_id, is_valid_resource_id + from azure.mgmt.core.tools import resource_id import json except ImportError: @@ -246,6 +260,7 @@ class AzureRMResource(AzureRMModuleBase): ), subresource=dict( type='list', + elements='dict', default=[] ), api_version=dict( @@ -261,6 +276,7 @@ class AzureRMResource(AzureRMModuleBase): ), status_code=dict( type='list', + elements='int', default=[200, 201, 202] ), idempotency=dict( @@ -309,6 +325,7 @@ class AzureRMResource(AzureRMModuleBase): for key in self.module_arg_spec: setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if self.state == 'absent': @@ -354,7 +371,7 @@ class AzureRMResource(AzureRMModuleBase): provider = self.url.split("/providers/")[1].split("/")[0] resourceType = self.url.split(provider + "/")[1].split("/")[0] url = "/subscriptions/" + self.subscription_id + "/providers/" + provider - api_versions = json.loads(self.mgmt_client.query(url, "GET", {'api-version': '2015-01-01'}, None, None, [200], 0, 0).text) + api_versions = json.loads(self.mgmt_client.query(url, "GET", {'api-version': '2015-01-01'}, None, None, [200], 0, 0).body()) for rt in api_versions['resourceTypes']: if rt['resourceType'].lower() == resourceType.lower(): self.api_version = rt['apiVersions'][0] @@ -384,7 +401,7 @@ class AzureRMResource(AzureRMModuleBase): needs_update = False else: try: - response = json.loads(original.text) + response = json.loads(original.body()) needs_update = (dict_merge(response, self.body) != response) except Exception: pass @@ -398,11 +415,11 @@ class AzureRMResource(AzureRMModuleBase): self.status_code, self.polling_timeout, self.polling_interval) - if self.state == 'present': + if self.state == 'present' and self.method != 'DELETE': try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: - response = response.text + response = response.context['deserialized_data'] else: response = None diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resource_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resource_info.py index d1af99ca2..eb5cd93e4 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resource_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resource_info.py @@ -22,25 +22,32 @@ options: url: description: - Azure RM Resource URL. + type: str api_version: description: - Specific API version to be used. + type: str provider: description: - Provider type, should be specified in no URL is given. + type: str resource_group: description: - Resource group to be used. - Required if URL is not specified. + type: str resource_type: description: - Resource type. + type: str resource_name: description: - Resource name. + type: str method: description: - The HTTP method of the request or response. It must be uppercase. + type: str choices: - GET - PUT @@ -53,16 +60,22 @@ options: subresource: description: - List of subresources. + type: list + elements: dict + default: [] suboptions: namespace: description: - Subresource namespace. + type: str type: description: - Subresource type. + type: str name: description: - Subresource name. + type: str extends_documentation_fragment: - azure.azcollection.azure @@ -73,18 +86,18 @@ author: ''' EXAMPLES = ''' - - name: Get scaleset info - azure_rm_resource_info: - resource_group: myResourceGroup - provider: compute - resource_type: virtualmachinescalesets - resource_name: myVmss - api_version: "2017-12-01" +- name: Get scaleset info + azure_rm_resource_info: + resource_group: myResourceGroup + provider: compute + resource_type: virtualmachinescalesets + resource_name: myVmss + api_version: "2017-12-01" - - name: Query all the resources in the resource group - azure_rm_resource_info: - resource_group: "{{ resource_group }}" - resource_type: resources +- name: Query all the resources in the resource group + azure_rm_resource_info: + resource_group: "{{ resource_group }}" + resource_type: resources ''' RETURN = ''' @@ -258,7 +271,7 @@ response: sample: { "offer": "UbuntuServer", "publisher": "Canonical", - "sku": "18.04-LTS", + "sku": "20_04-lts", "version": "latest" } osDisk: @@ -289,9 +302,7 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_rest import GenericRestClient try: - from msrestazure.azure_exceptions import CloudError - from msrest.service_client import ServiceClient - from msrestazure.tools import resource_id, is_valid_resource_id + from azure.mgmt.core.tools import resource_id import json except ImportError: @@ -320,7 +331,13 @@ class AzureRMResourceInfo(AzureRMModuleBase): ), subresource=dict( type='list', - default=[] + elements='dict', + default=[], + options=dict( + namespace=dict(type='str'), + type=dict(type='str'), + name=dict(type='str') + ) ), method=dict( type='str', @@ -353,6 +370,7 @@ class AzureRMResourceInfo(AzureRMModuleBase): for key in self.module_arg_spec: setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if self.url is None: @@ -394,7 +412,7 @@ class AzureRMResourceInfo(AzureRMModuleBase): provider = self.url.split("/providers/")[1].split("/")[0] resourceType = self.url.split(provider + "/")[1].split("/")[0] url = "/subscriptions/" + self.subscription_id + "/providers/" + provider - api_versions = json.loads(self.mgmt_client.query(url, self.method, {'api-version': '2015-01-01'}, None, None, [200], 0, 0).text) + api_versions = json.loads(self.mgmt_client.query(url, self.method, {'api-version': '2015-01-01'}, None, None, [200], 0, 0).body()) for rt in api_versions['resourceTypes']: if rt['resourceType'].lower() == resourceType.lower(): self.api_version = rt['apiVersions'][0] @@ -421,7 +439,7 @@ class AzureRMResourceInfo(AzureRMModuleBase): query_parameters['skiptoken'] = skiptoken response = self.mgmt_client.query(self.url, self.method, query_parameters, header_parameters, None, [200, 404], 0, 0) try: - response = json.loads(response.text) + response = json.loads(response.body()) if isinstance(response, dict): if response.get('value'): self.results['response'] = self.results['response'] + response['value'] diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resourcegroup.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resourcegroup.py index 553330ab1..2fa448fa8 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resourcegroup.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resourcegroup.py @@ -29,15 +29,18 @@ options: description: - Azure location for the resource group. Required when creating a new resource group. - Cannot be changed once resource group is created. + type: str name: description: - Name of the resource group. required: true + type: str state: description: - Assert the state of the resource group. Use C(present) to create or update and C(absent) to delete. - When C(absent) a resource group containing resources will not be removed unless the I(force) option is used. default: present + type: str choices: - absent - present @@ -52,24 +55,24 @@ author: ''' EXAMPLES = ''' - - name: Create a resource group - azure_rm_resourcegroup: - name: myResourceGroup - location: westus - tags: - testing: testing - delete: never - - - name: Delete a resource group - azure_rm_resourcegroup: - name: myResourceGroup - state: absent - - - name: Delete a resource group including resources it contains - azure_rm_resourcegroup: - name: myResourceGroup - force_delete_nonempty: yes - state: absent +- name: Create a resource group + azure_rm_resourcegroup: + name: myResourceGroup + location: westus + tags: + testing: testing + delete: never + +- name: Delete a resource group + azure_rm_resourcegroup: + name: myResourceGroup + state: absent + +- name: Delete a resource group including resources it contains + azure_rm_resourcegroup: + name: myResourceGroup + force_delete_nonempty: true + state: absent ''' RETURN = ''' contains_resources: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resourcegroup_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resourcegroup_info.py index 969143a17..d6cc6d27c 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resourcegroup_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resourcegroup_info.py @@ -24,6 +24,7 @@ options: name: description: - Limit results to a specific resource group. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -33,6 +34,8 @@ options: description: - List all resources under the resource group. - Note this will cost network overhead for each resource group. Suggest use this when I(name) set. + type: bool + extends_documentation_fragment: - azure.azcollection.azure @@ -44,23 +47,23 @@ author: ''' EXAMPLES = ''' - - name: Get facts for one resource group - azure_rm_resourcegroup_info: - name: myResourceGroup +- name: Get facts for one resource group + azure_rm_resourcegroup_info: + name: myResourceGroup - - name: Get facts for all resource groups - azure_rm_resourcegroup_info: +- name: Get facts for all resource groups + azure_rm_resourcegroup_info: - - name: Get facts by tags - azure_rm_resourcegroup_info: - tags: - - testing - - foo:bar +- name: Get facts by tags + azure_rm_resourcegroup_info: + tags: + - testing + - foo:bar - - name: Get facts for one resource group including resources it contains - azure_rm_resourcegroup_info: - name: myResourceGroup - list_resources: yes +- name: Get facts for one resource group including resources it contains + azure_rm_resourcegroup_info: + name: myResourceGroup + list_resources: true ''' RETURN = ''' resourcegroups: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roleassignment.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roleassignment.py index 6a930cc4b..f989146a6 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roleassignment.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roleassignment.py @@ -23,21 +23,25 @@ options: - The object id of assignee. This maps to the ID inside the Active Directory. - It can point to a user, service principal or security group. - Required when creating role assignment. + type: str aliases: - assignee id: description: - Fully qualified id of assignment to delete or create. - Mutually Exclusive with I(scope) and I(name) + type: str name: description: - Unique name of role assignment. - The role assignment name must be a GUID, sample as "3ce0cbb0-58c4-4e6d-a16d-99d86a78b3ca". - Mutually Exclusive with I(id) + type: str role_definition_id: description: - The role definition id used in the role assignment. - Required when creating role assignment. + type: str scope: description: - The scope of the role assignment to create. @@ -45,12 +49,14 @@ options: - /subscriptions/{subscription-id}/resourceGroups/{resource-group-name} for resource group. - /subscriptions/{subscription-id}/resourceGroups/{resource-group-name}/providers/{resource-provider}/{resource-type}/{resource-name} for resource. - Mutually Exclusive with I(id) + type: str state: description: - Assert the state of the role assignment. - Use C(present) to create or update a role assignment and C(absent) to delete it. - If C(present), then I(role_definition_id) and I(assignee_object_id) are both required default: present + type: str choices: - absent - present @@ -65,39 +71,39 @@ author: ''' EXAMPLES = ''' - - name: Create a role assignment - azure_rm_roleassignment: - scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - assignee_object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - role_definition_id: - "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/providers/Microsoft.Authorization/roleDefinitions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" - - - name: Create a role assignment - azure_rm_roleassignment: - name: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - assignee_object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - role_definition_id: - "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/providers/Microsoft.Authorization/roleDefinitions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" - - - name: Delete a role assignment - azure_rm_roleassignment: - name: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - state: absent - - - name: Delete a role assignment - azure_rm_roleassignment: - id: /subscriptions/xxx-sub-guid-xxx/resourceGroups/rgname/providers/Microsoft.Authorization/roleAssignments/xxx-assign-guid-xxx" - state: absent - - - name: Delete a role assignment - azure_rm_roleassignment: - scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - assignee_object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - role_definition_id: - "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/providers/Microsoft.Authorization/roleDefinitions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" - state: absent +- name: Create a role assignment + azure_rm_roleassignment: + scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + assignee_object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + role_definition_id: + "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/providers/Microsoft.Authorization/roleDefinitions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + +- name: Create a role assignment + azure_rm_roleassignment: + name: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + assignee_object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + role_definition_id: + "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/providers/Microsoft.Authorization/roleDefinitions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + +- name: Delete a role assignment + azure_rm_roleassignment: + name: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + state: absent + +- name: Delete a role assignment + azure_rm_roleassignment: + id: /subscriptions/xxx-sub-guid-xxx/resourceGroups/rgname/providers/Microsoft.Authorization/roleAssignments/xxx-assign-guid-xxx" + state: absent + +- name: Delete a role assignment + azure_rm_roleassignment: + scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + assignee_object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + role_definition_id: + "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/providers/Microsoft.Authorization/roleDefinitions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + state: absent ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roleassignment_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roleassignment_info.py index 4fa338a81..b77335a38 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roleassignment_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roleassignment_info.py @@ -22,6 +22,7 @@ options: description: - Object id of a user, group or service principal. - Mutually exclusive with I(name) and I(id). + type: str aliases: - assignee_object_id id: @@ -29,14 +30,17 @@ options: - Fqid of role assignment to look up. - If set, I(role_definition_id) and I(scope) will be silently ignored. - Mutually exclusive with I(assignee) and I(name). + type: str name: description: - Name of role assignment. - Requires that I(scope) also be set. - Mutual exclusive with I(assignee) and I(id). + type: str role_definition_id: description: - Resource id of role definition. + type: str scope: description: - The scope to query for role assignments. @@ -44,6 +48,7 @@ options: - /subscriptions/{subscription-id}/resourceGroups/{resourcegroup-name} for a resource group. - /subscriptions/{subscription-id}/resourceGroups/{resourcegroup-name}/providers/{resource-provider}/{resource-type}/{resource-name} for a resource. - By default will return all inhereted assignments from parent scopes, see I(strict_scope_match). + type: str strict_scope_match: description: - If strict_scope_match is True, role assignments will only be returned for the exact scope defined. @@ -62,28 +67,28 @@ author: ''' EXAMPLES = ''' - - name: Get role assignments for specific service principal - azure_rm_roleassignment_info: - assignee: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - - - name: Get role assignments for specific scope that matches specific role definition - azure_rm_roleassignment_info: - scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - role_definition_id: /subscriptions/xxx-sub-guid-xxx/providers/Microsoft.Authorization/roleDefinitions/xxx-role-guid-xxxx - - - name: Get role assignments for specific scope with no inherited assignments - azure_rm_roleassignment_info: - scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - strict_scope_match: True - - - name: Get role assignments by name - azure_rm_roleassignment_info: - scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - name: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - - - name: Get role assignments by id - azure_rm_roleassignment_info: - id: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/providers/Microsoft.Authorization/roleAssignments/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +- name: Get role assignments for specific service principal + azure_rm_roleassignment_info: + assignee: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + +- name: Get role assignments for specific scope that matches specific role definition + azure_rm_roleassignment_info: + scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + role_definition_id: /subscriptions/xxx-sub-guid-xxx/providers/Microsoft.Authorization/roleDefinitions/xxx-role-guid-xxxx + +- name: Get role assignments for specific scope with no inherited assignments + azure_rm_roleassignment_info: + scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + strict_scope_match: true + +- name: Get role assignments by name + azure_rm_roleassignment_info: + scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + name: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + +- name: Get role assignments by id + azure_rm_roleassignment_info: + id: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/providers/Microsoft.Authorization/roleAssignments/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roledefinition.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roledefinition.py index d1cc4c2a5..8683142d8 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roledefinition.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roledefinition.py @@ -81,17 +81,17 @@ author: ''' EXAMPLES = ''' - - name: Create a role definition - azure_rm_roledefinition: - name: myTestRole - scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myresourceGroup - permissions: - - actions: - - "Microsoft.Compute/virtualMachines/read" - data_actions: - - "Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write" - assignable_scopes: - - "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +- name: Create a role definition + azure_rm_roledefinition: + name: myTestRole + scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myresourceGroup + permissions: + - actions: + - "Microsoft.Compute/virtualMachines/read" + data_actions: + - "Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write" + assignable_scopes: + - "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" ''' RETURN = ''' @@ -108,11 +108,8 @@ from ansible.module_utils._text import to_native try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase - from msrestazure.azure_operation import AzureOperationPoller from azure.core.polling import LROPoller - from msrest.serialization import Model from azure.mgmt.authorization import AuthorizationManagementClient - from azure.mgmt.authorization.model import (RoleDefinition, Permission) except ImportError: # This is handled in azure_rm_common @@ -341,7 +338,7 @@ class AzureRMRoleDefinition(AzureRMModuleBase): response = self._client.role_definitions.create_or_update(role_definition_id=self.role['name'] if self.role else str(uuid.uuid4()), scope=self.scope, role_definition=role_definition) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: @@ -360,7 +357,7 @@ class AzureRMRoleDefinition(AzureRMModuleBase): try: response = self._client.role_definitions.delete(scope=scope, role_definition_id=role_definition_id) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as e: self.log('Error attempting to delete the role definition.') diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roledefinition_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roledefinition_info.py index 3899ce404..ce8ee238e 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roledefinition_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roledefinition_info.py @@ -47,14 +47,14 @@ author: ''' EXAMPLES = ''' - - name: List Role Definitions in scope - azure_rm_roledefinition_info: - scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup - - - name: Get Role Definition by name - azure_rm_roledefinition_info: - scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup - role_name: myRoleDefinition +- name: List Role Definitions in scope + azure_rm_roledefinition_info: + scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup + +- name: Get Role Definition by name + azure_rm_roledefinition_info: + scope: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup + role_name: myRoleDefinition ''' RETURN = ''' @@ -120,11 +120,8 @@ roledefinitions: sample: [ 'Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write' ] ''' -from ansible.module_utils._text import to_native - try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase - from msrest.serialization import Model from azure.mgmt.authorization import AuthorizationManagementClient except ImportError: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_route.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_route.py index dc1e79260..556c5395e 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_route.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_route.py @@ -20,23 +20,28 @@ options: description: - Name of resource group. required: true + type: str name: description: - Name of the route. required: true + type: str state: description: - Assert the state of the route. Use C(present) to create or update and C(absent) to delete. default: present + type: str choices: - absent - present address_prefix: description: - The destination CIDR to which the route applies. + type: str next_hop_type: description: - The type of Azure hop the packet should be sent to. + type: str choices: - virtual_network_gateway - vnet_local @@ -48,10 +53,12 @@ options: description: - The IP address packets should be forwarded to. - Next hop values are only allowed in routes where the next hop type is VirtualAppliance. + type: str route_table_name: description: - The name of the route table. required: true + type: str extends_documentation_fragment: @@ -64,20 +71,20 @@ author: ''' EXAMPLES = ''' - - name: Create a route - azure_rm_route: - resource_group: myResourceGroup - name: myRoute - address_prefix: 10.1.0.0/16 - next_hop_type: virtual_network_gateway - route_table_name: table - - - name: Delete a route - azure_rm_route: - resource_group: myResourceGroup - name: myRoute - route_table_name: table - state: absent +- name: Create a route + azure_rm_route: + resource_group: myResourceGroup + name: myRoute + address_prefix: 10.1.0.0/16 + next_hop_type: virtual_network_gateway + route_table_name: table + +- name: Delete a route + azure_rm_route: + resource_group: myResourceGroup + name: myRoute + route_table_name: table + state: absent ''' RETURN = ''' id: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_route_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_route_info.py index ee5311c21..c9cb3a0e7 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_route_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_route_info.py @@ -45,18 +45,17 @@ author: ''' EXAMPLES = ''' - - name: Get route - azure_rm_route_info: - resource_group: myResourceGroup - name: routename - route_table_name: routetabename +- name: Get route + azure_rm_route_info: + resource_group: myResourceGroup + name: routename + route_table_name: routetabename - - name: List routes - azure_rm_route_info: - resource_group: myResourceGroup - route_table_name: routetabename - +- name: List routes + azure_rm_route_info: + resource_group: myResourceGroup + route_table_name: routetabename ''' RETURN = ''' @@ -116,9 +115,6 @@ routes: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBase try: from azure.core.exceptions import ResourceNotFoundError - from azure.mgmt.network import NetworkManagementClient - from msrestazure.azure_operation import AzureOperationPoller - from msrest.polling import LROPoller except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_routetable.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_routetable.py index 7558907e9..94468d030 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_routetable.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_routetable.py @@ -20,14 +20,17 @@ options: description: - Name of resource group. required: true + type: str name: description: - Name of the route table. required: true + type: str state: description: - Assert the state of the route table. Use C(present) to create or update and C(absent) to delete. default: present + type: str choices: - absent - present @@ -40,6 +43,7 @@ options: description: - Region of the resource. - Derived from I(resource_group) if not specified. + type: str extends_documentation_fragment: - azure.azcollection.azure @@ -51,19 +55,19 @@ author: ''' EXAMPLES = ''' - - name: Create a route table - azure_rm_routetable: - resource_group: myResourceGroup - name: myRouteTable - disable_bgp_route_propagation: False - tags: - purpose: testing - - - name: Delete a route table - azure_rm_routetable: - resource_group: myResourceGroup - name: myRouteTable - state: absent +- name: Create a route table + azure_rm_routetable: + resource_group: myResourceGroup + name: myRouteTable + disable_bgp_route_propagation: false + tags: + purpose: testing + +- name: Delete a route table + azure_rm_routetable: + resource_group: myResourceGroup + name: myRouteTable + state: absent ''' RETURN = ''' changed: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_routetable_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_routetable_info.py index 901319ab8..56c8802ea 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_routetable_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_routetable_info.py @@ -23,9 +23,11 @@ options: name: description: - Limit results to a specific route table. + type: str resource_group: description: - Limit results in a specific resource group. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -41,20 +43,20 @@ author: ''' EXAMPLES = ''' - - name: Get facts for one route table - azure_rm_routetable_info: - name: Testing - resource_group: myResourceGroup - - - name: Get facts for all route tables - azure_rm_routetable_info: - resource_group: myResourceGroup - - - name: Get facts by tags - azure_rm_routetable_info: - tags: - - testing - - foo:bar +- name: Get facts for one route table + azure_rm_routetable_info: + name: Testing + resource_group: myResourceGroup + +- name: Get facts for all route tables + azure_rm_routetable_info: + resource_group: myResourceGroup + +- name: Get facts by tags + azure_rm_routetable_info: + tags: + - testing + - foo:bar ''' RETURN = ''' id: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_securitygroup.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_securitygroup.py index 28a9b8391..8b25449ca 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_securitygroup.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_securitygroup.py @@ -26,40 +26,142 @@ options: - The set of default rules automatically added to a security group at creation. - In general default rules will not be modified. Modify rules to shape the flow of traffic to or from a subnet or NIC. - See rules below for the makeup of a rule dict. + type: list + elements: dict + suboptions: + name: + description: + - Unique name for the rule. + type: str + required: true + description: + description: + - Short description of the rule's purpose. + type: str + protocol: + description: + - Accepted traffic protocol. + type: str + choices: + - Udp + - Tcp + - Icmp + - "*" + default: "*" + source_port_range: + description: + - Port or range of ports from which traffic originates. + - It can accept string type or a list of string type. + default: "*" + type: raw + destination_port_range: + description: + - Port or range of ports to which traffic is headed. + - It can accept string type or a list of string type. + default: "*" + type: raw + source_address_prefix: + description: + - The CIDR or source IP range. + - Asterisk C(*) can also be used to match all source IPs. + - Default tags such as C(VirtualNetwork), C(AzureLoadBalancer) and C(Internet) can also be used. + - If this is an ingress rule, specifies where network traffic originates from. + - It can accept string type or a list of string type. + - Asterisk C(*) and default tags can only be specified as single string type, not as a list of string. + type: raw + default: "*" + destination_address_prefix: + description: + - The destination address prefix. + - CIDR or destination IP range. + - Asterisk C(*) can also be used to match all source IPs. + - Default tags such as C(VirtualNetwork), C(AzureLoadBalancer) and C(Internet) can also be used. + - It can accept string type or a list of string type. + - Asterisk C(*) and default tags can only be specified as single string type, not as a list of string. + default: "*" + type: raw + source_application_security_groups: + description: + - List of the source application security groups. + - It could be list of resource id. + - It could be list of names in same resource group. + - It could be list of dict containing resource_group and name. + - It is mutually exclusive with C(source_address_prefix) and C(source_address_prefixes). + type: list + elements: raw + destination_application_security_groups: + description: + - List of the destination application security groups. + - It could be list of resource id. + - It could be list of names in same resource group. + - It could be list of dict containing I(resource_group) and I(name). + - It is mutually exclusive with C(destination_address_prefix) and C(destination_address_prefixes). + type: list + elements: raw + access: + description: + - Whether or not to allow the traffic flow. + type: str + choices: + - Allow + - Deny + default: Allow + priority: + description: + - Order in which to apply the rule. Must a unique integer between 100 and 4096 inclusive. + type: int + required: true + direction: + description: + - Indicates the direction of the traffic flow. + type: str + choices: + - Inbound + - Outbound + default: Inbound location: description: - Valid azure location. Defaults to location of the resource group. + type: str name: description: - Name of the security group to operate on. + type: str + required: true purge_default_rules: description: - Remove any existing rules not matching those defined in the default_rules parameter. type: bool - default: 'no' + default: false purge_rules: description: - Remove any existing rules not matching those defined in the rules parameters. type: bool - default: 'no' + default: false resource_group: description: - Name of the resource group the security group belongs to. required: true + type: str rules: description: - Set of rules shaping traffic flow to or from a subnet or NIC. Each rule is a dictionary. + type: list + elements: dict suboptions: name: description: - Unique name for the rule. + type: str required: true description: description: - Short description of the rule's purpose. + type: str protocol: description: - Accepted traffic protocol. + type: str choices: - Udp - Tcp @@ -71,11 +173,13 @@ options: - Port or range of ports from which traffic originates. - It can accept string type or a list of string type. default: "*" + type: raw destination_port_range: description: - Port or range of ports to which traffic is headed. - It can accept string type or a list of string type. default: "*" + type: raw source_address_prefix: description: - The CIDR or source IP range. @@ -84,6 +188,7 @@ options: - If this is an ingress rule, specifies where network traffic originates from. - It can accept string type or a list of string type. - Asterisk C(*) and default tags can only be specified as single string type, not as a list of string. + type: raw default: "*" destination_address_prefix: description: @@ -94,6 +199,7 @@ options: - It can accept string type or a list of string type. - Asterisk C(*) and default tags can only be specified as single string type, not as a list of string. default: "*" + type: raw source_application_security_groups: description: - List of the source application security groups. @@ -115,6 +221,7 @@ options: access: description: - Whether or not to allow the traffic flow. + type: str choices: - Allow - Deny @@ -122,10 +229,12 @@ options: priority: description: - Order in which to apply the rule. Must a unique integer between 100 and 4096 inclusive. + type: int required: true direction: description: - Indicates the direction of the traffic flow. + type: str choices: - Inbound - Outbound @@ -134,6 +243,7 @@ options: description: - Assert the state of the security group. Set to C(present) to create or update a security group. Set to C(absent) to remove a security group. default: present + type: str choices: - absent - present @@ -149,63 +259,62 @@ author: ''' EXAMPLES = ''' +- name: Create a security group + azure_rm_securitygroup: + resource_group: myResourceGroup + name: mysecgroup + purge_rules: true + rules: + - name: DenySSH + protocol: Tcp + destination_port_range: 22 + access: Deny + priority: 100 + direction: Inbound + - name: 'AllowSSH' + protocol: Tcp + source_address_prefix: + - '174.109.158.0/24' + - '174.109.159.0/24' + destination_port_range: 22 + access: Allow + priority: 101 + direction: Inbound + - name: 'AllowMultiplePorts' + protocol: Tcp + source_address_prefix: + - '174.109.158.0/24' + - '174.109.159.0/24' + destination_port_range: + - 80 + - 443 + access: Allow + priority: 102 -# Create a security group -- azure_rm_securitygroup: - resource_group: myResourceGroup - name: mysecgroup - purge_rules: yes - rules: - - name: DenySSH - protocol: Tcp - destination_port_range: 22 - access: Deny - priority: 100 - direction: Inbound - - name: 'AllowSSH' - protocol: Tcp - source_address_prefix: - - '174.109.158.0/24' - - '174.109.159.0/24' - destination_port_range: 22 - access: Allow - priority: 101 - direction: Inbound - - name: 'AllowMultiplePorts' - protocol: Tcp - source_address_prefix: - - '174.109.158.0/24' - - '174.109.159.0/24' - destination_port_range: - - 80 - - 443 - access: Allow - priority: 102 - -# Update rules on existing security group -- azure_rm_securitygroup: - resource_group: myResourceGroup - name: mysecgroup - rules: - - name: DenySSH - protocol: Tcp - destination_port_range: 22-23 - access: Deny - priority: 100 - direction: Inbound - - name: AllowSSHFromHome - protocol: Tcp - source_address_prefix: '174.109.158.0/24' - destination_port_range: 22-23 - access: Allow - priority: 102 - direction: Inbound - tags: - testing: testing - delete: on-exit - -# Create a securiy group with I(protocol=Icmp) -- azure_rm_securitygroup: +- name: Update rules on existing security group + azure_rm_securitygroup: + resource_group: myResourceGroup + name: mysecgroup + rules: + - name: DenySSH + protocol: Tcp + destination_port_range: 22-23 + access: Deny + priority: 100 + direction: Inbound + - name: AllowSSHFromHome + protocol: Tcp + source_address_prefix: '174.109.158.0/24' + destination_port_range: 22-23 + access: Allow + priority: 102 + direction: Inbound + tags: + testing: testing + delete: on-exit + +- name: Create a securiy group with I(protocol=Icmp) + azure_rm_securitygroup: name: mysecgroup resource_group: myResourceGroup rules: @@ -219,11 +328,11 @@ EXAMPLES = ''' protocol: Icmp priority: 106 -# Delete security group -- azure_rm_securitygroup: - resource_group: myResourceGroup - name: mysecgroup - state: absent +- name: Delete security group + azure_rm_securitygroup: + resource_group: myResourceGroup + name: mysecgroup + state: absent ''' RETURN = ''' @@ -417,14 +526,12 @@ state: try: from azure.core.exceptions import ResourceNotFoundError - from msrestazure.tools import is_valid_resource_id - from azure.mgmt.network import NetworkManagementClient + from azure.mgmt.core.tools import is_valid_resource_id except ImportError: # This is handled in azure_rm_common pass from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase -from ansible.module_utils.six import integer_types from ansible.module_utils._text import to_native @@ -633,13 +740,25 @@ class AzureRMSecurityGroup(AzureRMModuleBase): def __init__(self): self.module_arg_spec = dict( - default_rules=dict(type='list', elements='dict', options=rule_spec), + default_rules=dict( + type='list', + elements='dict', + options=rule_spec, + mutually_exclusive=[("source_application_security_groups", "source_address_prefix"), + ("destination_application_security_groups", "destination_address_prefix")] + ), location=dict(type='str'), name=dict(type='str', required=True), purge_default_rules=dict(type='bool', default=False), purge_rules=dict(type='bool', default=False), resource_group=dict(required=True, type='str'), - rules=dict(type='list', elements='dict', options=rule_spec), + rules=dict( + type='list', + elements='dict', + options=rule_spec, + mutually_exclusive=[("source_application_security_groups", "source_address_prefix"), + ("destination_application_security_groups", "destination_address_prefix")] + ), state=dict(type='str', default='present', choices=['present', 'absent']), ) @@ -659,14 +778,8 @@ class AzureRMSecurityGroup(AzureRMModuleBase): state=dict() ) - mutually_exclusive = [["source_application_security_group", "source_address_prefix"], - ["source_application_security_group", "source_address_prefixes"], - ["destination_application_security_group", "destination_address_prefix"], - ["destination_application_security_group", "destination_address_prefixes"]] - super(AzureRMSecurityGroup, self).__init__(self.module_arg_spec, - supports_check_mode=True, - mutually_exclusive=mutually_exclusive) + supports_check_mode=True) def exec_module(self, **kwargs): # tighten up poll interval for security groups; default 30s is an eternity diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_securitygroup_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_securitygroup_info.py index 2a549c631..19fe0c874 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_securitygroup_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_securitygroup_info.py @@ -24,10 +24,12 @@ options: name: description: - Only show results for a specific security group. + type: str resource_group: description: - Name of the resource group to use. required: true + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -44,15 +46,14 @@ author: ''' EXAMPLES = ''' - - name: Get facts for one security group - azure_rm_securitygroup_info: - resource_group: myResourceGroup - name: secgroup001 - - - name: Get facts for all security groups - azure_rm_securitygroup_info: - resource_group: myResourceGroup - +- name: Get facts for one security group + azure_rm_securitygroup_info: + resource_group: myResourceGroup + name: secgroup001 + +- name: Get facts for all security groups + azure_rm_securitygroup_info: + resource_group: myResourceGroup ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebus.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebus.py index 07db88849..80c94e9a7 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebus.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebus.py @@ -20,23 +20,28 @@ options: description: - Name of resource group. required: true + type: str name: description: - Name of the servicebus namespace. required: true + type: str state: description: - Assert the state of the servicebus. Use C(present) to create or update and use C(absen) to delete. default: present + type: str choices: - absent - present location: description: - The servicebus's location. + type: str sku: description: - Namespace SKU. + type: str choices: - standard - basic @@ -55,10 +60,10 @@ author: EXAMPLES = ''' - name: Create a namespace azure_rm_servicebus: - name: deadbeef - location: eastus - tags: - key1: value1 + name: deadbeef + location: eastus + tags: + key1: value1 ''' RETURN = ''' id: @@ -75,7 +80,6 @@ except ImportError: # This is handled in azure_rm_common pass -from ansible.module_utils.common.dict_transformations import _snake_to_camel, _camel_to_snake from ansible.module_utils._text import to_native from datetime import datetime, timedelta diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebus_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebus_info.py index 246bb514b..5ccd4dea7 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebus_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebus_info.py @@ -23,9 +23,11 @@ options: name: description: - Limit results to a specific servicebus. + type: str resource_group: description: - Limit results in a specific resource group. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -37,9 +39,12 @@ options: - A namespace is a scoping container for all messaging components. - Multiple queues and topics can reside within a single namespace, and namespaces often serve as application containers. - Required when I(type=namespace). + type: str type: description: - Type of the resource. + type: str + required: true choices: - namespace - queue @@ -49,6 +54,7 @@ options: description: - Topic name. - Required when I(type=subscription). + type: str show_sas_policies: description: - Whether to show the SAS policies. @@ -375,8 +381,7 @@ servicebuses: ''' try: - from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, azure_id_to_dict - from msrestazure.azure_exceptions import CloudError + from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase except Exception: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebusqueue.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebusqueue.py index edb810374..f63da177a 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebusqueue.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebusqueue.py @@ -20,20 +20,24 @@ options: description: - Name of resource group. required: true + type: str name: description: - Name of the queue. required: true + type: str namespace: description: - Servicebus namespace name. - A namespace is a scoping container for all messaging components. - Multiple queues and topics can reside within a single namespace, and namespaces often serve as application containers. required: true + type: str state: description: - Assert the state of the queue. Use C(present) to create or update and use C(absent) to delete. default: present + type: str choices: - absent - present @@ -68,9 +72,11 @@ options: forward_dead_lettered_messages_to: description: - Queue or topic name to forward the Dead Letter message for a queue. + type: str forward_to: description: - Queue or topic name to forward the messages for a queue. + type: str lock_duration_in_seconds: description: - Timespan duration of a peek-lock. @@ -106,6 +112,7 @@ options: status: description: - Status of the entity. + type: str choices: - active - disabled diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebussaspolicy.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebussaspolicy.py index 3acb2f479..63d71a375 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebussaspolicy.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebussaspolicy.py @@ -20,14 +20,17 @@ options: description: - Name of resource group. required: true + type: str name: description: - Name of the SAS policy. required: true + type: str state: description: - Assert the state of the route. Use C(present) to create or update and C(absent) to delete. default: present + type: str choices: - absent - present @@ -36,14 +39,17 @@ options: - Manage SAS policy for a namespace without C(queue) or C(topic) set. - Manage SAS policy for a queue or topic under this namespace. required: true + type: str queue: description: - Type of the messaging queue. - Cannot set C(topc) when this field set. + type: str topic: description: - Name of the messaging topic. - Cannot set C(queue) when this field set. + type: str regenerate_primary_key: description: - Regenerate the SAS policy primary key. @@ -57,7 +63,8 @@ options: rights: description: - Claim rights of the SAS policy. - required: True + - Required when creating. + type: str choices: - manage - listen @@ -153,10 +160,6 @@ except ImportError: # This is handled in azure_rm_common pass -from ansible.module_utils.common.dict_transformations import _snake_to_camel, _camel_to_snake -from ansible.module_utils._text import to_native -from datetime import datetime, timedelta - class AzureRMServiceBusSASPolicy(AzureRMModuleBase): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebustopic.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebustopic.py index c2eb25e86..75ae477eb 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebustopic.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebustopic.py @@ -20,20 +20,24 @@ options: description: - Name of resource group. required: true + type: str name: description: - Name of the topic. required: true + type: str namespace: description: - Servicebus namespace name. - A namespace is a scoping container for all messaging components. - Multipletopics can reside within a single namespace. + type: str required: true state: description: - Assert the state of the topic. Use C(present) to create or update and use C(absent) to delete. default: present + type: str choices: - absent - present @@ -85,6 +89,7 @@ options: status: description: - Status of the entity. + type: str choices: - active - disabled @@ -156,7 +161,7 @@ class AzureRMServiceBusTopic(AzureRMModuleBase): max_size_in_mb=dict(type='int'), max_message_size_in_kb=dict(type='int'), name=dict(type='str', required=True), - namespace=dict(type='str'), + namespace=dict(type='str', required=True), requires_duplicate_detection=dict(type='bool'), resource_group=dict(type='str', required=True), state=dict(type='str', default='present', choices=['present', 'absent']), diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebustopicsubscription.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebustopicsubscription.py index b6cc523db..aa9ae40dd 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebustopicsubscription.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebustopicsubscription.py @@ -20,14 +20,17 @@ options: description: - Name of resource group. required: true + type: str name: description: - Name of the servicebus subscription. required: true + type: str state: description: - Assert the state of the servicebus subscription. Use C(present) to create or update and use C(absent) to delete. default: present + type: str choices: - absent - present @@ -37,10 +40,12 @@ options: - A namespace is a scoping container for all messaging components. - Multiple subscriptions and topics can reside within a single namespace, and namespaces often serve as application containers. required: true + type: str topic: description: - Topic name which the subscription subscribe to. required: true + type: str auto_delete_on_idle_in_seconds: description: - Time idle interval after which a subscription is automatically deleted. @@ -67,9 +72,11 @@ options: forward_dead_lettered_messages_to: description: - Queue or topic name to forward the Dead Letter message for a subscription. + type: str forward_to: description: - Queue or topic name to forward the messages for a subscription. + type: str lock_duration_in_seconds: description: - Timespan duration of a peek-lock. @@ -92,6 +99,7 @@ options: status: description: - Status of the entity. + type: str choices: - active - disabled diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_snapshot.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_snapshot.py index 15c814414..bd3acd9bd 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_snapshot.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_snapshot.py @@ -24,6 +24,7 @@ options: name: description: - Resource name. + required: true type: str location: description: @@ -130,11 +131,6 @@ import time 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 -try: - from msrestazure.azure_exceptions import CloudError -except ImportError: - # this is handled in azure_rm_common - pass class Actions: @@ -252,6 +248,7 @@ class AzureRMSnapshots(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) resource_group = self.get_resource_group(self.resource_group) @@ -328,6 +325,7 @@ class AzureRMSnapshots(AzureRMModuleBaseExt): def create_update_resource(self): # self.log('Creating / Updating the Snapshot instance {0}'.format(self.)) + response = None try: response = self.mgmt_client.query(url=self.url, method='PUT', @@ -337,14 +335,16 @@ class AzureRMSnapshots(AzureRMModuleBaseExt): expected_status_codes=self.status_code, polling_timeout=600, polling_interval=30) - except CloudError as exc: + except Exception as exc: self.log('Error attempting to create the Snapshot instance.') self.fail('Error creating the Snapshot instance: {0}'.format(str(exc))) - try: - response = json.loads(response.text) - except Exception: - response = {'text': response.text} + if hasattr(response, 'body'): + response = json.loads(response.body()) + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Create or Updating fail, no match message return, return info as {0}".format(response)) return response @@ -359,7 +359,7 @@ class AzureRMSnapshots(AzureRMModuleBaseExt): expected_status_codes=self.status_code, polling_timeout=600, polling_interval=30) - except CloudError as e: + except Exception as e: self.log('Error attempting to delete the Snapshot instance.') self.fail('Error deleting the Snapshot instance: {0}'.format(str(e))) @@ -377,11 +377,11 @@ class AzureRMSnapshots(AzureRMModuleBaseExt): expected_status_codes=self.status_code, polling_timeout=600, polling_interval=30) - response = json.loads(response.text) + response = json.loads(response.body()) found = True self.log("Response : {0}".format(response)) # self.log("Snapshot instance : {0} found".format(response.name)) - except CloudError as e: + except Exception as e: self.log('Did not find the Snapshot instance.') if found is True: return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqldatabase.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqldatabase.py index 972125b2e..b66e886b6 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqldatabase.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqldatabase.py @@ -21,20 +21,25 @@ options: description: - The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal. required: True + type: str server_name: description: - The name of the server. required: True + type: str name: description: - The name of the database to be operated on (updated or created). required: True + type: str location: description: - Resource location. If not set, location from the resource group will be used as default. + type: str collation: description: - The collation of the database. If not I(create_mode=default), this value is ignored. + type: str create_mode: description: - Specifies the mode of database creation. @@ -46,6 +51,7 @@ options: - C(restore), Creates a database by restoring a backup of a deleted database. - C(restore_long_term_retention_backup), Creates a database by restoring from a long term retention vault. - C(copy), C(non_readable_secondary), C(online_secondary) and C(restore_long_term_retention_backup) are not supported for C(data_warehouse) edition. + type: str choices: - 'copy' - 'default' @@ -59,24 +65,29 @@ options: description: - Required unless I(create_mode=default) or I(create_mode=restore_long_term_retention_backup). - Specifies the resource ID of the source database. + type: str source_database_deletion_date: description: - Required if I(create_mode=restore) and I(source_database_id) is the deleted database's original resource id when it existed (as opposed to its current restorable dropped database ID), then this value is required. Specifies the time that the database was deleted. + type: str restore_point_in_time: description: - Required if I(create_mode=point_in_time_restore), this value is required. If I(create_mode=restore), this value is optional. - Specifies the point in time (ISO8601 format) of the source database that will be restored to create the new database. - Must be greater than or equal to the source database's earliestRestoreDate value. + type: str recovery_services_recovery_point_resource_id: description: - Required if I(create_mode=restore_long_term_retention_backup), then this value is required. - Specifies the resource ID of the recovery point to restore from. + type: str edition: description: - (Deprecate)The edition of the database. The DatabaseEditions enumeration contains all the valid editions. - This option will be deprecated in 2.11, use I(sku) instead. - Cannot set C(sku) when this field set. + type: str choices: - 'web' - 'business' @@ -95,32 +106,40 @@ options: - To see possible values, query the capabilities API (/subscriptions/{subscriptionId}/providers/Microsoft.Sql/locations/{locationID}/capabilities) referred to by operationId:'Capabilities_ListByLocation'. - Cannot set C(edition) when this field set. + type: dict suboptions: name: description: - Name of the database SKU, typically, a letter + Number code, e.g. P3 required: True + type: str tier: description: - The tier or edition of the particular SKU, e.g. Basic, Premium + type: str capacity: description: - Capacity of the particular SKU. + type: int size: description: - Size of the particular SKU + type: str family: description: - If the service has different generations of hardware, for the same SKU, then that can be used here + type: str max_size_bytes: description: - The max size of the database expressed in bytes. - If not I(create_mode=default), this value is ignored. - To see possible values, query the capabilities API (/subscriptions/{subscriptionId}/providers/Microsoft.Sql/locations/{locationID}/capabilities). referred to by operationId:'Capabilities_ListByLocation'. + type: str elastic_pool_name: description: - The name of the elastic pool the database is in. Not supported for I(edition=data_warehouse). + type: str read_scale: description: - If the database is a geo-secondary, indicates whether read-only connections are allowed to this database or not. @@ -132,6 +151,7 @@ options: - Indicates the name of the sample schema to apply when creating this database. - If not I(create_mode=default), this value is ignored. - Not supported for I(edition=data_warehouse). + type: str choices: - 'adventure_works_lt' zone_redundant: @@ -140,17 +160,18 @@ options: type: bool default: False force_update: - description: - - SQL Database will be updated if given parameters differ from existing resource state. - - To force SQL Database update in any circumstances set this parameter to True. - type: bool + description: + - SQL Database will be updated if given parameters differ from existing resource state. + - To force SQL Database update in any circumstances set this parameter to True. + type: bool state: - description: - - Assert the state of the SQL Database. Use C(present) to create or update an SQL Database and C(absent) to delete it. - default: present - choices: - - absent - - present + description: + - Assert the state of the SQL Database. Use C(present) to create or update an SQL Database and C(absent) to delete it. + default: present + type: str + choices: + - absent + - present extends_documentation_fragment: - azure.azcollection.azure @@ -162,42 +183,41 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) SQL Database - azure_rm_sqldatabase: - resource_group: myResourceGroup - server_name: sqlcrudtest-5961 - name: testdb - location: eastus - - - name: Restore SQL Database - azure_rm_sqldatabase: - resource_group: myResourceGroup - server_name: sqlcrudtest-5961 - name: restoreddb - location: eastus - create_mode: restore - restorable_dropped_database_id: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Sql/s - ervers/testsvr/restorableDroppedDatabases/testdb2,131444841315030000" - - - name: Create SQL Database in Copy Mode - azure_rm_sqldatabase: - resource_group: myResourceGroup - server_name: sqlcrudtest-5961 - name: copydb - location: eastus - create_mode: copy - source_database_id: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Sql/servers/tests - vr/databases/testdb" - - - name: Create (or update) SQL Database with SKU - azure_rm_sqldatabase: - resource_group: myResourceGroup - server_name: sqlcrudtest-5961 - name: testdb - location: eastus - sku: - name: S0 - +- name: Create (or update) SQL Database + azure_rm_sqldatabase: + resource_group: myResourceGroup + server_name: sqlcrudtest-5961 + name: testdb + location: eastus + +- name: Restore SQL Database + azure_rm_sqldatabase: + resource_group: myResourceGroup + server_name: sqlcrudtest-5961 + name: restoreddb + location: eastus + create_mode: restore + restorable_dropped_database_id: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Sql/s + ervers/testsvr/restorableDroppedDatabases/testdb2,131444841315030000" + +- name: Create SQL Database in Copy Mode + azure_rm_sqldatabase: + resource_group: myResourceGroup + server_name: sqlcrudtest-5961 + name: copydb + location: eastus + create_mode: copy + source_database_id: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Sql/servers/tests + vr/databases/testdb" + +- name: Create (or update) SQL Database with SKU + azure_rm_sqldatabase: + resource_group: myResourceGroup + server_name: sqlcrudtest-5961 + name: testdb + location: eastus + sku: + name: S0 ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqldatabase_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqldatabase_info.py index 9c9af2501..4a53ec243 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqldatabase_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqldatabase_info.py @@ -21,16 +21,20 @@ options: description: - The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal. required: True + type: str server_name: description: - The name of the server. required: True + type: str name: description: - The name of the database. + type: str elastic_pool_name: description: - The name of the elastic pool. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -46,22 +50,22 @@ author: ''' EXAMPLES = ''' - - name: Get instance of SQL Database - azure_rm_sqldatabase_info: - resource_group: testrg - server_name: testserver - name: testdb - - - name: List instances of SQL Database - azure_rm_sqldatabase_info: - resource_group: testrg - server_name: testserver - elastic_pool_name: testep - - - name: List instances of SQL Database - azure_rm_sqldatabase_info: - resource_group: testrg - server_name: testserver +- name: Get instance of SQL Database + azure_rm_sqldatabase_info: + resource_group: testrg + server_name: testserver + name: testdb + +- name: List instances of SQL Database + azure_rm_sqldatabase_info: + resource_group: testrg + server_name: testserver + elastic_pool_name: testep + +- name: List instances of SQL Database + azure_rm_sqldatabase_info: + resource_group: testrg + server_name: testserver ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlelasticpool.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlelasticpool.py index 563e9111b..b74432ba0 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlelasticpool.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlelasticpool.py @@ -119,25 +119,25 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) SQL Elastic Pool - azure_rm_elastic_pool: - resource_group: myResourceGroup - server_name: sqlcrudtest-5961 - name: testEP - zone_redundant: False - sku: - name: GP_Gen5 - family: Gen5 - capacity: 3 - tags: - key1: value1 - - - name: Delete SQL Elastic Pool - azure_rm_elastic_pool: - resource_group: myResourceGroup - server_name: sqlcrudtest-5961 - name: testEP - state: absent +- name: Create (or update) SQL Elastic Pool + azure_rm_elastic_pool: + resource_group: myResourceGroup + server_name: sqlcrudtest-5961 + name: testEP + zone_redundant: false + sku: + name: GP_Gen5 + family: Gen5 + capacity: 3 + tags: + key1: value1 + +- name: Delete SQL Elastic Pool + azure_rm_elastic_pool: + resource_group: myResourceGroup + server_name: sqlcrudtest-5961 + name: testEP + state: absent ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlelasticpool_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlelasticpool_info.py index 4ac9ac86e..2aed051c7 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlelasticpool_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlelasticpool_info.py @@ -48,16 +48,16 @@ author: ''' EXAMPLES = ''' - - name: Get instance of SQL Elastic Pool - azure_rm_sqlelasticpool_info: - resource_group: testrg - server_name: testserver - name: testEP +- name: Get instance of SQL Elastic Pool + azure_rm_sqlelasticpool_info: + resource_group: testrg + server_name: testserver + name: testEP - - name: List instances of SQL Elastic Pool - azure_rm_sqlelasticpool_info: - resource_group: testrg - server_name: testserver +- name: List instances of SQL Elastic Pool + azure_rm_sqlelasticpool_info: + resource_group: testrg + server_name: testserver ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlfirewallrule.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlfirewallrule.py index 059256a07..e41e4f66c 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlfirewallrule.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlfirewallrule.py @@ -21,26 +21,32 @@ options: description: - The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal. required: True + type: str server_name: description: - The name of the server. required: True + type: str name: description: - The name of the firewall rule. required: True + type: str start_ip_address: description: - The start IP address of the firewall rule. - Must be IPv4 format. Use value C(0.0.0.0) to represent all Azure-internal IP addresses. + type: str end_ip_address: description: - The end IP address of the firewall rule. - Must be IPv4 format. Must be greater than or equal to I(start_ip_address). Use value C(0.0.0.0) to represent all Azure-internal IP addresses. + type: str state: description: - State of the SQL Database. Use C(present) to create or update an SQL Database and C(absent) to delete it. default: present + type: str choices: - absent - present @@ -54,13 +60,13 @@ author: ''' EXAMPLES = ''' - - name: Create (or update) Firewall Rule - azure_rm_sqlfirewallrule: - resource_group: myResourceGroup - server_name: firewallrulecrudtest-6285 - name: firewallrulecrudtest-5370 - start_ip_address: 172.28.10.136 - end_ip_address: 172.28.10.138 +- name: Create (or update) Firewall Rule + azure_rm_sqlfirewallrule: + resource_group: myResourceGroup + server_name: firewallrulecrudtest-6285 + name: firewallrulecrudtest-5370 + start_ip_address: 172.28.10.136 + end_ip_address: 172.28.10.138 ''' RETURN = ''' @@ -78,7 +84,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError - from azure.core.polling import LROPoller from azure.mgmt.sql.models import FirewallRule except ImportError: # This is handled in azure_rm_common diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlfirewallrule_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlfirewallrule_info.py index 7c9bb0459..73c22f5b9 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlfirewallrule_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlfirewallrule_info.py @@ -21,13 +21,16 @@ options: description: - The name of the resource group that contains the server. required: True + type: str server_name: description: - The name of the server. required: True + type: str name: description: - The name of the firewall rule. + type: str extends_documentation_fragment: - azure.azcollection.azure @@ -38,16 +41,16 @@ author: ''' EXAMPLES = ''' - - name: Get instance of SQL Firewall Rule - azure_rm_sqlfirewallrule_info: - resource_group: myResourceGroup - server_name: testserver - name: testrule - - - name: List instances of SQL Firewall Rule - azure_rm_sqlfirewallrule_info: - resource_group: myResourceGroup - server_name: testserver +- name: Get instance of SQL Firewall Rule + azure_rm_sqlfirewallrule_info: + resource_group: myResourceGroup + server_name: testserver + name: testrule + +- name: List instances of SQL Firewall Rule + azure_rm_sqlfirewallrule_info: + resource_group: myResourceGroup + server_name: testserver ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlmanagedinstance.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlmanagedinstance.py index c9d905343..b59421062 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlmanagedinstance.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlmanagedinstance.py @@ -513,7 +513,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError - from azure.core.polling import LROPoller except ImportError: pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlmanagedinstance_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlmanagedinstance_info.py index ad0b11012..5434cb6a4 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlmanagedinstance_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlmanagedinstance_info.py @@ -40,19 +40,19 @@ author: ''' EXAMPLES = ''' - - name: Get SQL managed instance by name - azure_rm_sqlmanagedinstance_info: - resource_group: testrg - name: testinstancename +- name: Get SQL managed instance by name + azure_rm_sqlmanagedinstance_info: + resource_group: testrg + name: testinstancename - - name: List SQL managed instance by resource group - azure_rm_sqlmanagedinstance_info: - resource_group: testrg +- name: List SQL managed instance by resource group + azure_rm_sqlmanagedinstance_info: + resource_group: testrg - - name: List SQL manged instance by subscription and filter by tags - azure_rm_sqlmanagedinstance_info: - tags: - - foo +- name: List SQL manged instance by subscription and filter by tags + azure_rm_sqlmanagedinstance_info: + tags: + - foo ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlserver.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlserver.py index f4cf45f08..bffd8e7ab 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlserver.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlserver.py @@ -20,27 +20,34 @@ options: resource_group: description: - The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal. + type: str required: True name: description: - The name of the server. + type: str required: True location: description: - Resource location. + type: str admin_username: description: - Username of the SQL administrator account for server. Once created it cannot be changed. + type: str admin_password: description: - Password of the SQL administrator account for server (required for server creation). + type: str version: description: - The version of the server. For example C(12.0). + type: str identity: description: - The identity type. Set this to C(SystemAssigned) in order to automatically create and assign an Azure Active Directory principal for the resource. - Possible values include C(SystemAssigned). + type: str minimal_tls_version: description: - Require clients to use a specified TLS version. @@ -111,6 +118,7 @@ options: description: - State of the SQL server. Use C(present) to create or update a server and use C(absent) to delete a server. default: present + type: str choices: - absent - present diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlserver_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlserver_info.py index 06e34ea22..51351d3c3 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlserver_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlserver_info.py @@ -20,10 +20,12 @@ options: resource_group: description: - The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal. + type: str required: True server_name: description: - The name of the server. + type: str extends_documentation_fragment: - azure.azcollection.azure @@ -35,14 +37,14 @@ author: ''' EXAMPLES = ''' - - name: Get instance of SQL Server - azure_rm_sqlserver_info: - resource_group: myResourceGroup - server_name: server_name +- name: Get instance of SQL Server + azure_rm_sqlserver_info: + resource_group: myResourceGroup + server_name: server_name - - name: List instances of SQL Server - azure_rm_sqlserver_info: - resource_group: myResourceGroup +- name: List instances of SQL Server + azure_rm_sqlserver_info: + resource_group: myResourceGroup ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageaccount.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageaccount.py index d3b5bb807..c7c280ef4 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageaccount.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageaccount.py @@ -21,16 +21,20 @@ options: description: - Name of the resource group to use. required: true + type: str aliases: - resource_group_name name: description: - Name of the storage account to update or create. + type: str + required: true state: description: - State of the storage account. Use C(present) to create or update a storage account and use C(absent) to delete an account. - C(failover) is used to failover the storage account to its secondary. This process can take up to a hour. default: present + type: str choices: - absent - present @@ -38,11 +42,13 @@ options: location: description: - Valid Azure location. Defaults to location of the resource group. + type: str account_type: description: - Type of storage account. Required when creating a storage account. - C(Standard_ZRS) and C(Premium_LRS) accounts cannot be changed to other account types. - Other account types cannot be changed to C(Standard_ZRS) or C(Premium_LRS). + type: str choices: - Premium_LRS - Standard_GRS @@ -61,6 +67,7 @@ options: - Only one custom domain is supported per storage account at this time. - To clear the existing custom domain, use an empty string for the custom domain name property. - Can be added to an existing storage account. Will be ignored during storage account creation. + type: dict aliases: - custom_dns_domain_suffix kind: @@ -68,6 +75,7 @@ options: - The kind of storage. - The C(FileStorage) and (BlockBlobStorage) only used when I(account_type=Premium_LRS) or I(account_type=Premium_ZRS). default: 'Storage' + type: str choices: - Storage - StorageV2 @@ -82,6 +90,7 @@ options: access_tier: description: - The access tier for this storage account. Required when I(kind=BlobStorage). + type: str choices: - Hot - Cool @@ -101,6 +110,7 @@ options: description: - The minimum required version of Transport Layer Security (TLS) for requests to a storage account. - If omitted, new account creation will default to null which is currently interpreted to TLS1_0. Existing accounts will not be modified. + type: str choices: - TLS1_0 - TLS1_1 @@ -109,6 +119,7 @@ options: public_network_access: description: - Allow or disallow public network access to Storage Account. + type: str choices: - Enabled - Disabled @@ -129,6 +140,7 @@ options: description: - Default firewall traffic rule. - If I(default_action=Allow) no other settings have effect. + type: str choices: - Allow - Deny @@ -140,28 +152,37 @@ options: - It can be any combination of the example C(AzureServices), C(Logging), C(Metrics). - If no Azure components are allowed, explicitly set I(bypass=""). default: AzureServices + type: str virtual_network_rules: description: - A list of subnets and their actions. + type: list + elements: dict suboptions: id: description: - The complete path to the subnet. + type: str action: description: - The only logical I(action=Allow) because this setting is only accessible when I(default_action=Deny). default: 'Allow' + type: str ip_rules: description: - A list of IP addresses or ranges in CIDR format. + type: list + elements: dict suboptions: value: description: - The IP address or range. + type: str action: description: - The only logical I(action=Allow) because this setting is only accessible when I(default_action=Deny). default: 'Allow' + type: str blob_cors: description: - Specifies CORS rules for the Blob service. @@ -288,65 +309,65 @@ author: ''' EXAMPLES = ''' - - name: remove account, if it exists - azure_rm_storageaccount: - resource_group: myResourceGroup - name: clh0002 - state: absent - - - name: create an account - azure_rm_storageaccount: - resource_group: myResourceGroup - name: clh0002 - type: Standard_RAGRS - tags: - testing: testing - delete: on-exit - - - name: Create an account with kind of FileStorage - azure_rm_storageaccount: - resource_group: myResourceGroup - name: c1h0002 - type: Premium_LRS - kind: FileStorage - tags: - testing: testing - - - name: configure firewall and virtual networks - azure_rm_storageaccount: - resource_group: myResourceGroup - name: clh0002 - type: Standard_RAGRS - network_acls: - bypass: AzureServices,Metrics - default_action: Deny - virtual_network_rules: - - id: /subscriptions/mySubscriptionId/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVnet/subnets/mySubnet - action: Allow - ip_rules: - - value: 1.2.3.4 - action: Allow - - value: 123.234.123.0/24 - action: Allow - - - name: create an account with blob CORS - azure_rm_storageaccount: - resource_group: myResourceGroup - name: clh002 - type: Standard_RAGRS - blob_cors: - - allowed_origins: - - http://www.example.com/ - allowed_methods: - - GET - - POST - allowed_headers: - - x-ms-meta-data* - - x-ms-meta-target* - - x-ms-meta-abc - exposed_headers: - - x-ms-meta-* - max_age_in_seconds: 200 +- name: remove account, if it exists + azure_rm_storageaccount: + resource_group: myResourceGroup + name: clh0002 + state: absent + +- name: create an account + azure_rm_storageaccount: + resource_group: myResourceGroup + name: clh0002 + type: Standard_RAGRS + tags: + testing: testing + delete: on-exit + +- name: Create an account with kind of FileStorage + azure_rm_storageaccount: + resource_group: myResourceGroup + name: c1h0002 + type: Premium_LRS + kind: FileStorage + tags: + testing: testing + +- name: configure firewall and virtual networks + azure_rm_storageaccount: + resource_group: myResourceGroup + name: clh0002 + type: Standard_RAGRS + network_acls: + bypass: AzureServices,Metrics + default_action: Deny + virtual_network_rules: + - id: /subscriptions/mySubscriptionId/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVnet/subnets/mySubnet + action: Allow + ip_rules: + - value: 1.2.3.4 + action: Allow + - value: 123.234.123.0/24 + action: Allow + +- name: create an account with blob CORS + azure_rm_storageaccount: + resource_group: myResourceGroup + name: clh002 + type: Standard_RAGRS + blob_cors: + - allowed_origins: + - http://www.example.com/ + allowed_methods: + - GET + - POST + allowed_headers: + - x-ms-meta-data* + - x-ms-meta-target* + - x-ms-meta-abc + exposed_headers: + - x-ms-meta-* + max_age_in_seconds: 200 ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageaccount_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageaccount_info.py index 2b0c301c3..75f179b6f 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageaccount_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageaccount_info.py @@ -24,9 +24,11 @@ options: name: description: - Only show results for a specific account. + type: str resource_group: description: - Limit results to a resource group. Required when filtering by name. + type: str aliases: - resource_group_name tags: @@ -61,20 +63,20 @@ author: ''' EXAMPLES = ''' - - name: Get facts for one account - azure_rm_storageaccount_info: - resource_group: myResourceGroup - name: clh0002 +- name: Get facts for one account + azure_rm_storageaccount_info: + resource_group: myResourceGroup + name: clh0002 - - name: Get facts for all accounts in a resource group - azure_rm_storageaccount_info: - resource_group: myResourceGroup +- name: Get facts for all accounts in a resource group + azure_rm_storageaccount_info: + resource_group: myResourceGroup - - name: Get facts for all accounts by tags - azure_rm_storageaccount_info: - tags: - - testing - - foo:bar +- name: Get facts for all accounts by tags + azure_rm_storageaccount_info: + tags: + - testing + - foo:bar ''' RETURN = ''' @@ -477,6 +479,7 @@ storageaccounts: description: - The account key for the secondary_endpoints sample: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + type: str georeplication_stats: description: - Parameters related to the status of geo-replication. @@ -533,11 +536,6 @@ storageaccounts: sample: error.html ''' -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 from ansible.module_utils._text import to_native @@ -609,7 +607,7 @@ class AzureRMStorageAccountInfo(AzureRMModuleBase): account = None try: expand = None - if(self.show_georeplication_stats): + if (self.show_georeplication_stats): expand = 'georeplicationstats' account = self.storage_client.storage_accounts.get_properties(self.resource_group, self.name, expand=expand) return [account] diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageblob.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageblob.py index 0999494be..868069f42 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageblob.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageblob.py @@ -26,6 +26,7 @@ options: description: - Name of the storage account to use. required: true + type: str aliases: - account_name - storage_account @@ -34,10 +35,12 @@ options: - Name of a blob object within the container. aliases: - blob_name + type: str blob_type: description: - Type of blob object. default: block + type: str choices: - block - page @@ -46,31 +49,39 @@ options: description: - Name of a blob container within the storage account. required: true + type: str aliases: - container_name content_type: description: - Set the blob content-type header. For example C(image/png). + type: str cache_control: description: - Set the blob cache-control header. + type: str content_disposition: description: - Set the blob content-disposition header. + type: str content_encoding: description: - Set the blob encoding header. + type: str content_language: description: - Set the blob content-language header. + type: str content_md5: description: - Set the blob md5 hash value. + type: str dest: description: - Destination file path. Use with state C(present) to download a blob. aliases: - destination + type: path force: description: - Overwrite existing blob or file when uploading or downloading. Force deletion of a container that contains blobs. @@ -80,19 +91,23 @@ options: description: - Name of the resource group to use. required: true + type: str aliases: - resource_group_name src: description: - Source file path. Use with state C(present) to upload a blob. + type: str aliases: - source batch_upload_src: description: - Batch upload source directory. Use with state C(present) to upload batch of files under the directory. + type: path batch_upload_dst: description: - Base directory in container when upload batch of files. + type: path state: description: - State of a container or blob. @@ -105,6 +120,7 @@ options: to download. If a blob (uploading) or a file (downloading) already exists, it will not be overwritten unless I(force=true). default: present + type: str choices: - absent - present @@ -112,6 +128,7 @@ options: description: - A container's level of public access. By default containers are private. - Can only be set at time of container creation. + type: str choices: - container - blob diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageshare.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageshare.py index e4749b87a..747a24ac0 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageshare.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageshare.py @@ -57,7 +57,23 @@ options: - The maximum size of the file share, in gigabytes. Must be greater than 0, and less than or equal to 5TB (5120). For large file shares, the maximum size is 102400. By default 102400 type: int - + enabled_protocols: + description: + - The authentication protocol that is used for the file share. + - Can only be specified when creating a share. + type: str + choices: + - SMB + - NFS + root_squash: + description: + - The property is for NFS share only. + - The default is C(NoRootSquash). + type: str + choices: + - NoRootSquash + - RootSquash + - AllSquash extends_documentation_fragment: - azure.azcollection.azure @@ -80,6 +96,15 @@ EXAMPLES = ''' key1: value1 key2: value2 +- name: Create share with enalbed protocols + azure_rm_storageshare: + name: "{{ share_name }}" + resource_group: "{{ resource_group }}" + account_name: "{{ storage_account }}" + access_tier: "{{ access_tier }}" + root_squash: RootSquash + enabled_protocols: NFS + - name: Delete storage share azure_rm_storageshare: name: testShare @@ -184,6 +209,8 @@ class AzureRMStorageShare(AzureRMModuleBase): choices=['TransactionOptimized', 'Hot', 'Cool', 'Premium']), quota=dict(type='int', default=None), metadata=dict(type='dict', default=None), + root_squash=dict(type='str', choices=['NoRootSquash', 'RootSquash', 'AllSquash']), + enabled_protocols=dict(type='str', choices=['SMB', 'NFS']), ) self.results = dict( changed=False, @@ -196,6 +223,8 @@ class AzureRMStorageShare(AzureRMModuleBase): self.state = None self.quota = None self.metadata = None + self.root_squash = None + self.enabled_protocols = None self.to_do = Actions.NoAction @@ -259,7 +288,9 @@ class AzureRMStorageShare(AzureRMModuleBase): ''' return ((self.access_tier is not None) and (self.access_tier != old_response.get('access_tier')) or (self.quota is not None) and (self.quota != old_response.get('share_quota')) or - (self.metadata is not None) and (self.metadata != old_response.get('metadata'))) + (self.metadata is not None) and (self.metadata != old_response.get('metadata')) or + (self.root_squash is not None) and (self.root_squash != old_response.get('root_squash')) or + (self.enabled_protocols is not None) and (self.enabled_protocols != old_response.get('enabled_protocols'))) def get_share(self): ''' @@ -294,6 +325,8 @@ class AzureRMStorageShare(AzureRMModuleBase): share_quota=storage_share.share_quota, access_tier=storage_share.access_tier, access_tier_change_time=storage_share.access_tier_change_time, + root_squash=storage_share.root_squash, + enabled_protocols=storage_share.enabled_protocols ) def create_storage_share(self): @@ -308,7 +341,9 @@ class AzureRMStorageShare(AzureRMModuleBase): share_name=self.name, file_share=dict(access_tier=self.access_tier, share_quota=self.quota, - metadata=self.metadata)) + metadata=self.metadata, + root_squash=self.root_squash, + enabled_protocols=self.enabled_protocols)) except Exception as e: self.fail("Error creating file share {0} : {1}".format(self.name, str(e))) return self.get_share() @@ -323,7 +358,9 @@ class AzureRMStorageShare(AzureRMModuleBase): file_share_details = dict( access_tier=self.access_tier if self.access_tier else old_responce.get('access_tier'), share_quota=self.quota if self.quota else old_responce.get('share_quota'), - metadata=self.metadata if self.metadata else old_responce.get('metadata') + metadata=self.metadata if self.metadata else old_responce.get('metadata'), + enabled_protocols=self.enabled_protocols if self.enabled_protocols else old_responce.get('enabled_protocols'), + root_squash=self.root_squash if self.root_squash else old_responce.get('self.root_squash') ) try: self.storage_client.file_shares.update(resource_group_name=self.resource_group, diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_subnet.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_subnet.py index 063ba1504..ec7117c37 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_subnet.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_subnet.py @@ -23,13 +23,16 @@ options: description: - Name of resource group. required: true + type: str name: description: - Name of the subnet. required: true + type: str address_prefix_cidr: description: - CIDR defining the IPv4 address space of the subnet. Must be valid within the context of the virtual network. + type: str aliases: - address_prefix address_prefixes_cidr: @@ -38,20 +41,23 @@ options: - If set I(address_prefix), It will not set. aliases: - address_prefixes - type: list version_added: "1.0.0" + type: list + elements: str security_group: description: - Existing security group with which to associate the subnet. - It can be the security group name which is in the same resource group. - Can be the resource ID of the security group. - Can be a dict containing the I(name) and I(resource_group) of the security group. + type: raw aliases: - security_group_name state: description: - Assert the state of the subnet. Use C(present) to create or update a subnet and use C(absent) to delete a subnet. default: present + type: str choices: - absent - present @@ -59,6 +65,7 @@ options: description: - Name of an existing virtual network with which the subnet is or will be associated. required: true + type: str aliases: - virtual_network route_table: @@ -67,19 +74,23 @@ options: - Can be the name or resource ID of the route table. - Can be a dict containing the I(name) and I(resource_group) of the route table. - Without this configuration, the associated route table will be dissociate. If there is no associated route table, it has no impact. + type: raw service_endpoints: description: - An array of service endpoints. type: list + elements: dict suboptions: service: description: - The type of the endpoint service. required: True + type: str locations: description: - A list of locations. type: list + elements: str private_endpoint_network_policies: description: - C(Enabled) or C(Disabled) apply network policies on private endpoints in the subnet. @@ -100,15 +111,18 @@ options: description: - An array of delegations. type: list + elements: dict suboptions: name: description: - The name of delegation. + type: str required: True serviceName: description: - The type of the endpoint service. required: True + type: str choices: - Microsoft.Web/serverFarms - Microsoft.ContainerInstance/containerGroups @@ -143,6 +157,8 @@ options: description: - A list of actions. type: list + elements: str + default: [] nat_gateway: description: - Existing NAT Gateway with which to associate the subnet. @@ -161,59 +177,59 @@ author: ''' EXAMPLES = ''' - - name: Create a subnet - azure_rm_subnet: - resource_group: myResourceGroup - virtual_network_name: myVirtualNetwork - name: mySubnet - address_prefix_cidr: "10.1.0.0/24" - - - name: Create a subnet refer nsg from other resource group - azure_rm_subnet: - resource_group: myResourceGroup - virtual_network_name: myVirtualNetwork - name: mySubnet - address_prefix_cidr: "10.1.0.0/16" - security_group: - name: secgroupfoo - resource_group: mySecondResourceGroup - route_table: route - - - name: Create a subnet with service endpoint - azure_rm_subnet: - resource_group: myResourceGroup - virtual_network_name: myVirtualNetwork - name: mySubnet - address_prefix_cidr: "10.1.0.0/16" - service_endpoints: - - service: "Microsoft.Sql" - locations: - - "eastus" - - - name: Create a subnet with delegations - azure_rm_subnet: - resource_group: myResourceGroup - virtual_network_name: myVirtualNetwork - name: mySubnet - address_prefix_cidr: "10.1.0.0/16" - delegations: - - name: 'mydeleg' - serviceName: 'Microsoft.ContainerInstance/containerGroups' - - - name: Create a subnet with an associated NAT Gateway - azure_rm_subnet: - resource_group: myResourceGroup - virtual_network_name: myVirtualNetwork - name: mySubnet - address_prefix_cidr: "10.1.0.0/16" - nat_gateway: myNatGateway - - - name: Delete a subnet - azure_rm_subnet: - resource_group: myResourceGroup - virtual_network_name: myVirtualNetwork - name: mySubnet - state: absent +- name: Create a subnet + azure_rm_subnet: + resource_group: myResourceGroup + virtual_network_name: myVirtualNetwork + name: mySubnet + address_prefix_cidr: "10.1.0.0/24" + +- name: Create a subnet refer nsg from other resource group + azure_rm_subnet: + resource_group: myResourceGroup + virtual_network_name: myVirtualNetwork + name: mySubnet + address_prefix_cidr: "10.1.0.0/16" + security_group: + name: secgroupfoo + resource_group: mySecondResourceGroup + route_table: route + +- name: Create a subnet with service endpoint + azure_rm_subnet: + resource_group: myResourceGroup + virtual_network_name: myVirtualNetwork + name: mySubnet + address_prefix_cidr: "10.1.0.0/16" + service_endpoints: + - service: "Microsoft.Sql" + locations: + - "eastus" + +- name: Create a subnet with delegations + azure_rm_subnet: + resource_group: myResourceGroup + virtual_network_name: myVirtualNetwork + name: mySubnet + address_prefix_cidr: "10.1.0.0/16" + delegations: + - name: 'mydeleg' + serviceName: 'Microsoft.ContainerInstance/containerGroups' + +- name: Create a subnet with an associated NAT Gateway + azure_rm_subnet: + resource_group: myResourceGroup + virtual_network_name: myVirtualNetwork + name: mySubnet + address_prefix_cidr: "10.1.0.0/16" + nat_gateway: myNatGateway + +- name: Delete a subnet + azure_rm_subnet: + resource_group: myResourceGroup + virtual_network_name: myVirtualNetwork + name: mySubnet + state: absent ''' RETURN = ''' @@ -313,7 +329,7 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError - from msrestazure.tools import is_valid_resource_id + from azure.mgmt.core.tools import is_valid_resource_id except ImportError: # This is handled in azure_rm_common pass @@ -340,6 +356,7 @@ delegations_spec = dict( ), actions=dict( type='list', + elements='str', default=[] ) ) @@ -387,11 +404,16 @@ class AzureRMSubnet(AzureRMModuleBase): state=dict(type='str', default='present', choices=['present', 'absent']), virtual_network_name=dict(type='str', required=True, aliases=['virtual_network']), address_prefix_cidr=dict(type='str', aliases=['address_prefix']), - address_prefixes_cidr=dict(type='list', aliases=['address_prefixes']), + address_prefixes_cidr=dict(type='list', aliases=['address_prefixes'], elements='str'), security_group=dict(type='raw', aliases=['security_group_name']), route_table=dict(type='raw'), service_endpoints=dict( - type='list' + type='list', + elements='dict', + options=dict( + service=dict(type='str', required=True), + locations=dict(type='list', elements='str') + ) ), private_endpoint_network_policies=dict( type='str', @@ -485,7 +507,7 @@ class AzureRMSubnet(AzureRMModuleBase): else: subnet['private_endpoint_network_policies'] = results['private_endpoint_network_policies'] if self.private_link_service_network_policies is not None: - if results['private_link_service_network_policies'] != self.private_link_service_network_policies is not None: + if results['private_link_service_network_policies'] != self.private_link_service_network_policies: self.log("CHANGED: subnet {0} private_link_service_network_policies".format(self.private_link_service_network_policies)) changed = True results['private_link_service_network_policies'] = self.private_link_service_network_policies diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_subnet_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_subnet_info.py index ec75ff6b9..eb004a891 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_subnet_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_subnet_info.py @@ -21,13 +21,16 @@ options: description: - The name of the resource group. required: True + type: str virtual_network_name: description: - The name of the virtual network. required: True + type: str name: description: - The name of the subnet. + type: str extends_documentation_fragment: - azure.azcollection.azure @@ -38,17 +41,17 @@ author: ''' EXAMPLES = ''' - - name: Get facts of specific subnet - azure_rm_subnet_info: - resource_group: myResourceGroup - virtual_network_name: myVirtualNetwork - name: mySubnet +- name: Get facts of specific subnet + azure_rm_subnet_info: + resource_group: myResourceGroup + virtual_network_name: myVirtualNetwork + name: mySubnet - - name: List facts for all subnets in virtual network - azure_rm_subnet_info: - resource_group: myResourceGroup - virtual_network_name: myVirtualNetwork - name: mySubnet +- name: List facts for all subnets in virtual network + azure_rm_subnet_info: + resource_group: myResourceGroup + virtual_network_name: myVirtualNetwork + name: mySubnet ''' RETURN = ''' @@ -192,7 +195,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_subscription_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_subscription_info.py index 9caeb3ef7..ec544d41c 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_subscription_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_subscription_info.py @@ -63,13 +63,13 @@ EXAMPLES = ''' - name: Get facts for all subscriptions, including ones that are disabled. azure_rm_subscription_info: - all: True + all: true - name: Get facts for subscriptions containing tags provided. azure_rm_subscription_info: tags: - - testing - - foo:bar + - testing + - foo:bar ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanager.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanager.py index 422a8df14..7764b7142 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanager.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanager.py @@ -20,24 +20,29 @@ options: description: - Name of a resource group where the Traffic Manager profile exists or will be created. required: true + type: str name: description: - Name of the Traffic Manager profile. required: true + type: str state: description: - Assert the state of the Traffic Manager profile. Use C(present) to create or update a Traffic Manager profile and C(absent) to delete it. default: present + type: str choices: - absent - present location: description: - Valid azure location. Defaults to 'global'. + type: str profile_status: description: - The status of the Traffic Manager profile. default: Enabled + type: str choices: - Enabled - Disabled @@ -45,6 +50,7 @@ options: description: - The traffic routing method of the Traffic Manager profile. default: Performance + type: str choices: - Performance - Priority @@ -53,22 +59,30 @@ options: dns_config: description: - The DNS settings of the Traffic Manager profile. + type: dict suboptions: relative_name: description: - The relative DNS name provided by this Traffic Manager profile. - If no provided, name of the Traffic Manager will be used + type: str ttl: description: - The DNS Time-To-Live (TTL), in seconds. - default: 60 + type: int monitor_config: description: - The endpoint monitoring settings of the Traffic Manager profile. + type: dict suboptions: + profile_monitor_status: + description: + - The profile-level monitoring status of the Traffic Manager. + type: str protocol: description: - The protocol (HTTP, HTTPS or TCP) used to probe for endpoint health. + type: str choices: - HTTP - HTTPS @@ -76,18 +90,23 @@ options: port: description: - The TCP port used to probe for endpoint health. + type: int path: description: - The path relative to the endpoint domain name used to probe for endpoint health. + type: str interval_in_seconds: description: - The monitor interval for endpoints in this profile. + type: int timeout_in_seconds: description: - The monitor timeout for endpoints in this profile. + type: int tolerated_number_of_failures: description: - The number of consecutive failed health check before declaring an endpoint in this profile Degraded after the next failed health check. + type: int default: protocol: HTTP port: 80 @@ -95,28 +114,39 @@ options: endpoints: description: - The list of endpoints in the Traffic Manager profile. + type: list + elements: dict + default: [] suboptions: + endpoint_monitor_status: + description: + - The monitoring status of the endpoint. + type: str id: description: - Fully qualified resource Id for the resource. + type: str name: description: - The name of the endpoint. - required: true + type: str type: description: - The type of the endpoint. Ex- Microsoft.network/TrafficManagerProfiles/ExternalEndpoints. - required: true + type: str target_resource_id: description: - The Azure Resource URI of the of the endpoint. - Not applicable to endpoints of type 'ExternalEndpoints'. + type: str target: description: - The fully-qualified DNS name of the endpoint. + type: str endpoint_status: description: - The status of the endpoint. + type: str choices: - Enabled - Disabled @@ -124,63 +154,69 @@ options: description: - The weight of this endpoint when using the 'Weighted' traffic routing method. - Possible values are from 1 to 1000. + type: int priority: description: - The priority of this endpoint when using the 'Priority' traffic routing method. - Possible values are from 1 to 1000, lower values represent higher priority. - This is an optional parameter. If specified, it must be specified on all endpoints. - No two endpoints can share the same priority value. + type: int endpoint_location: description: - Specifies the location of the external or nested endpoints when using the 'Performance' traffic routing method. + type: str min_child_endpoints: description: - The minimum number of endpoints that must be available in the child profile in order for the parent profile to be considered available. - Only applicable to endpoint of type 'NestedEndpoints'. + type: int geo_mapping: description: - The list of countries/regions mapped to this endpoint when using the 'Geographic' traffic routing method. + type: list + elements: str extends_documentation_fragment: - azure.azcollection.azure - azure.azcollection.azure_tags author: - - "Hai Cao <t-haicao@microsoft.com>" + - Hai Cao (@caohai) ''' EXAMPLES = ''' - - name: Create a Traffic Manager Profile - azure_rm_trafficmanager: - name: tmtest - resource_group: tmt - location: global - profile_status: Enabled - traffic_routing_method: Priority - dns_config: - relative_name: tmtest - ttl: 60 - monitor_config: - protocol: HTTPS - port: 80 - path: '/' - endpoints: - - name: e1 - type: Microsoft.network/TrafficManagerProfiles/ExternalEndpoints - endpoint_location: West US 2 - endpoint_status: Enabled - priority: 2 - target: 1.2.3.4 - weight: 1 - tags: - Environment: Test - - - name: Delete a Traffic Manager Profile - azure_rm_trafficmanager: - state: absent - name: tmtest - resource_group: tmt +- name: Create a Traffic Manager Profile + azure_rm_trafficmanager: + name: tmtest + resource_group: tmt + location: global + profile_status: Enabled + traffic_routing_method: Priority + dns_config: + relative_name: tmtest + ttl: 60 + monitor_config: + protocol: HTTPS + port: 80 + path: '/' + endpoints: + - name: e1 + type: Microsoft.network/TrafficManagerProfiles/ExternalEndpoints + endpoint_location: West US 2 + endpoint_status: Enabled + priority: 2 + target: 1.2.3.4 + weight: 1 + tags: + Environment: Test + +- name: Delete a Traffic Manager Profile + azure_rm_trafficmanager: + state: absent + name: tmtest + resource_group: tmt ''' RETURN = ''' state: @@ -330,7 +366,7 @@ dns_config_spec = dict( monitor_config_spec = dict( profile_monitor_status=dict(type='str'), - protocol=dict(type='str'), + protocol=dict(type='str', choices=['HTTP', 'HTTPS', 'TCP']), port=dict(type='int'), path=dict(type='str'), interval_in_seconds=dict(type='int'), @@ -344,7 +380,7 @@ endpoint_spec = dict( type=dict(type='str'), target_resource_id=dict(type='str'), target=dict(type='str'), - endpoint_status=dict(type='str'), + endpoint_status=dict(type='str', choices=['Enabled', 'Disabled']), weight=dict(type='int'), priority=dict(type='int'), endpoint_location=dict(type='str'), diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanagerendpoint.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanagerendpoint.py index df87ed93f..8acf7ede9 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanagerendpoint.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanagerendpoint.py @@ -35,6 +35,7 @@ options: description: - The type of the endpoint. required: true + type: str choices: - azure_endpoints - external_endpoints @@ -83,6 +84,7 @@ options: description: - Assert the state of the Traffic Manager endpoint. Use C(present) to create or update a Traffic Manager endpoint and C(absent) to delete it. default: present + type: str choices: - absent - present @@ -97,16 +99,16 @@ author: ''' EXAMPLES = ''' - - name: create a endpoint for a traffic manager profile - azure_rm_trafficmanagerendpoint: - resource_group: testresourcegroup - profile_name: myprofilename - name: testendpoint1 - type: external_endpoints - location: westus - priority: 2 - weight: 1 - target: 1.2.3.4 +- name: create a endpoint for a traffic manager profile + azure_rm_trafficmanagerendpoint: + resource_group: testresourcegroup + profile_name: myprofilename + name: testendpoint1 + type: external_endpoints + location: westus + priority: 2 + weight: 1 + target: 1.2.3.4 ''' RETURN = ''' @@ -119,14 +121,12 @@ id: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/trafficManagerProfiles/testProfil e/externalEndpoints/testendpoint" ''' -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, normalize_location_name +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.mgmt.trafficmanager.models import ( - Endpoint, DnsConfig, MonitorConfig - ) + from azure.mgmt.trafficmanager.models import Endpoint except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanagerendpoint_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanagerendpoint_info.py index 94bd2ac87..e25608553 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanagerendpoint_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanagerendpoint_info.py @@ -23,17 +23,21 @@ options: name: description: - Limit results to a specific Traffic Manager endpoint. + type: str resource_group: description: - The resource group to search for the desired Traffic Manager profile. required: True + type: str profile_name: description: - Name of Traffic Manager Profile. required: True + type: str type: description: - Type of endpoint. + type: str choices: - azure_endpoints - external_endpoints @@ -48,17 +52,16 @@ author: ''' EXAMPLES = ''' - - name: Get endpoints facts of a Traffic Manager profile - azure_rm_trafficmanagerendpoint_info: - resource_group: myResourceGroup - profile_name: Testing - - - name: Get specific endpoint of a Traffic Manager profile - azure_rm_trafficmanager_info: - resource_group: myResourceGroup - profile_name: Testing - name: test_external_endpoint - +- name: Get endpoints facts of a Traffic Manager profile + azure_rm_trafficmanagerendpoint_info: + resource_group: myResourceGroup + profile_name: Testing + +- name: Get specific endpoint of a Traffic Manager profile + azure_rm_trafficmanager_info: + resource_group: myResourceGroup + profile_name: Testing + name: test_external_endpoint ''' RETURN = ''' @@ -150,8 +153,6 @@ except Exception: # handled in azure_rm_common pass -import re - AZURE_OBJECT_CLASS = 'TrafficManagerEndpoints' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanagerprofile.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanagerprofile.py index b529666d3..c74cd8ccd 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanagerprofile.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanagerprofile.py @@ -20,14 +20,17 @@ options: description: - Name of a resource group where the Traffic Manager profile exists or will be created. required: true + type: str name: description: - Name of the Traffic Manager profile. required: true + type: str state: description: - Assert the state of the Traffic Manager profile. Use C(present) to create or update a Traffic Manager profile and C(absent) to delete it. default: present + type: str choices: - absent - present @@ -35,11 +38,13 @@ options: description: - Valid Azure location. Defaults to C(global) because in default public Azure cloud, Traffic Manager profile can only be deployed globally. - Reference U(https://docs.microsoft.com/en-us/azure/traffic-manager/quickstart-create-traffic-manager-profile#create-a-traffic-manager-profile). + type: str default: global profile_status: description: - The status of the Traffic Manager profile. default: enabled + type: str choices: - enabled - disabled @@ -47,6 +52,7 @@ options: description: - The traffic routing method of the Traffic Manager profile. default: performance + type: str choices: - performance - priority @@ -55,33 +61,42 @@ options: dns_config: description: - The DNS settings of the Traffic Manager profile. + type: dict suboptions: relative_name: description: - The relative DNS name provided by this Traffic Manager profile. - If not provided, name of the Traffic Manager will be used. + type: str ttl: description: - The DNS Time-To-Live (TTL), in seconds. type: int - default: 60 monitor_config: description: - The endpoint monitoring settings of the Traffic Manager profile. + type: dict suboptions: + profile_monitor_status: + description: + - The profile-level monitoring status of the Traffic Manager. + type: str protocol: description: - The protocol C(HTTP), C(HTTPS) or C(TCP) used to probe for endpoint health. + type: str choices: - - HTTP - HTTPS + - HTTP - TCP port: description: - The TCP port used to probe for endpoint health. + type: int path: description: - The path relative to the endpoint domain name used to probe for endpoint health. + type: str interval: description: - The monitor interval for endpoints in this profile in seconds. @@ -93,6 +108,7 @@ options: tolerated_failures: description: - The number of consecutive failed health check before declaring an endpoint in this profile Degraded after the next failed health check. + type: int default: protocol: HTTP port: 80 @@ -109,28 +125,28 @@ author: ''' EXAMPLES = ''' - - name: Create a Traffic Manager Profile - azure_rm_trafficmanagerprofile: - name: tmtest - resource_group: myResourceGroup - location: global - profile_status: enabled - routing_method: priority - dns_config: - relative_name: tmtest - ttl: 60 - monitor_config: - protocol: HTTPS - port: 80 - path: '/' - tags: - Environment: Test - - - name: Delete a Traffic Manager Profile - azure_rm_trafficmanagerprofile: - state: absent - name: tmtest - resource_group: myResourceGroup +- name: Create a Traffic Manager Profile + azure_rm_trafficmanagerprofile: + name: tmtest + resource_group: myResourceGroup + location: global + profile_status: enabled + routing_method: priority + dns_config: + relative_name: tmtest + ttl: 60 + monitor_config: + protocol: HTTPS + port: 80 + path: '/' + tags: + Environment: Test + +- name: Delete a Traffic Manager Profile + azure_rm_trafficmanagerprofile: + state: absent + name: tmtest + resource_group: myResourceGroup ''' RETURN = ''' id: @@ -156,7 +172,7 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError from azure.mgmt.trafficmanager.models import ( - Profile, Endpoint, DnsConfig, MonitorConfig + Profile, DnsConfig, MonitorConfig ) except ImportError: # This is handled in azure_rm_common @@ -240,7 +256,7 @@ dns_config_spec = dict( monitor_config_spec = dict( profile_monitor_status=dict(type='str'), - protocol=dict(type='str'), + protocol=dict(type='str', choices=['HTTP', 'HTTPS', 'TCP']), port=dict(type='int'), path=dict(type='str'), interval=dict(type='int'), diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanagerprofile_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanagerprofile_info.py index 43a3492de..e8477e370 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanagerprofile_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_trafficmanagerprofile_info.py @@ -23,9 +23,11 @@ options: name: description: - Limit results to a specific Traffic Manager profile. + type: str resource_group: description: - The resource group to search for the desired Traffic Manager profile. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -41,18 +43,18 @@ author: ''' EXAMPLES = ''' - - name: Get facts for one Traffic Manager profile - azure_rm_trafficmanager_info: - name: Testing - resource_group: myResourceGroup - - - name: Get facts for all Traffic Manager profiles - azure_rm_trafficmanager_info: - - - name: Get facts by tags - azure_rm_trafficmanager_info: - tags: - - Environment:Test +- name: Get facts for one Traffic Manager profile + azure_rm_trafficmanager_info: + name: Testing + resource_group: myResourceGroup + +- name: Get facts for all Traffic Manager profiles + azure_rm_trafficmanager_info: + +- name: Get facts by tags + azure_rm_trafficmanager_info: + tags: + - Environment:Test ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualhub.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualhub.py index d29abf3be..4de5a13f3 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualhub.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualhub.py @@ -208,23 +208,23 @@ author: ''' EXAMPLES = ''' - - name: Create a VirtualHub - azure_rm_virtualhub: - resource_group: myResourceGroup - name: my_virtual_hub_name - address_prefix: 10.2.0.0/24 - sku: Standard - location: eastus - enable_virtual_router_route_propogation: false - virtual_wan: - id: /subscriptions/xxx-xxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualWans/fredwan - - - name: Delete VirtualHub - azure_rm_virtualhub: - resource_group: myResourceGroup - name: my_virtual_hub_name - location: eastus - state: absent +- name: Create a VirtualHub + azure_rm_virtualhub: + resource_group: myResourceGroup + name: my_virtual_hub_name + address_prefix: 10.2.0.0/24 + sku: Standard + location: eastus + enable_virtual_router_route_propogation: false + virtual_wan: + id: /subscriptions/xxx-xxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualWans/fredwan + +- name: Delete VirtualHub + azure_rm_virtualhub: + resource_group: myResourceGroup + name: my_virtual_hub_name + location: eastus + state: absent ''' RETURN = ''' @@ -493,7 +493,6 @@ state: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt try: - from msrestazure.azure_operation import AzureOperationPoller from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller except ImportError: @@ -733,7 +732,7 @@ class AzureRMVirtualHub(AzureRMModuleBaseExt): response = self.network_client.virtual_hubs.begin_create_or_update(resource_group_name=self.resource_group, virtual_hub_name=self.name, virtual_hub_parameters=self.body) - if isinstance(response, AzureOperationPoller) or isinstance(response, LROPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: self.log('Error attempting to create the VirtualHub instance.') diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualhub_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualhub_info.py index b7c1b8fae..0a81abee4 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualhub_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualhub_info.py @@ -33,18 +33,17 @@ author: ''' EXAMPLES = ''' - - name: Get virtual hub info by name - azure_rm_virtualhub_info: - resource_group: myResourceGroup - name: virtualHub +- name: Get virtual hub info by name + azure_rm_virtualhub_info: + resource_group: myResourceGroup + name: virtualHub - - name: Get virtual hub info by resource group - azure_rm_virtualhub_info: - resource_group: myResourceGroup - - - name: Get birtual hub info by sub - azure_rm_virtualhub_info: +- name: Get virtual hub info by resource group + azure_rm_virtualhub_info: + resource_group: myResourceGroup +- name: Get birtual hub info by sub + azure_rm_virtualhub_info: ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualhubconnection.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualhubconnection.py index 5208f665e..a14caf799 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualhubconnection.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualhubconnection.py @@ -155,7 +155,6 @@ EXAMPLES = ''' vhub_name: testhub name: Myconnection state: absent - ''' RETURN = ''' @@ -289,7 +288,6 @@ state: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt try: - from msrestazure.azure_operation import AzureOperationPoller from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller except ImportError: @@ -467,7 +465,7 @@ class AzureRMVirtualHubConnection(AzureRMModuleBaseExt): virtual_hub_name=self.vhub_name, connection_name=self.name, hub_virtual_network_connection_parameters=self.body) - if isinstance(response, AzureOperationPoller) or isinstance(response, LROPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: self.log('Error attempting to create the VirtualHub instance.') diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualhubconnection_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualhubconnection_info.py index d2d01dc25..d12d689d3 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualhubconnection_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualhubconnection_info.py @@ -40,16 +40,16 @@ author: ''' EXAMPLES = ''' - - name: Get virtual hub connection info by name - azure_rm_virtualhubconnection_info: - resource_group: myResourceGroup - virtual_hub_name: virtualHub - name: vhubname +- name: Get virtual hub connection info by name + azure_rm_virtualhubconnection_info: + resource_group: myResourceGroup + virtual_hub_name: virtualHub + name: vhubname - - name: Get virtual hub connection info by resource group - azure_rm_virtualhubconnection_info: - resource_group: myResourceGroup - virtual_hub_name: virtualHub +- name: Get virtual hub connection info by resource group + azure_rm_virtualhubconnection_info: + resource_group: myResourceGroup + virtual_hub_name: virtualHub ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachine.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachine.py index 9fe82d75a..35435b821 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachine.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachine.py @@ -30,16 +30,19 @@ options: description: - Name of the resource group containing the VM. required: true + type: str name: description: - Name of the VM. required: true + type: str custom_data: description: - Data made available to the VM and used by C(cloud-init). - Only used on Linux images with C(cloud-init) enabled. - Consult U(https://docs.microsoft.com/en-us/azure/virtual-machines/linux/using-cloud-init#cloud-init-overview) for cloud-init ready images. - To enable cloud-init on a Linux image, follow U(https://docs.microsoft.com/en-us/azure/virtual-machines/linux/cloudinit-prepare-custom-image). + type: str state: description: - State of the VM. @@ -47,15 +50,23 @@ options: - Set to C(absent) to remove a VM. - Does not affect power state. Use I(started)/I(allocated)/I(restarted) parameters to change the power state of a VM. default: present + type: str choices: - absent - present started: description: - Whether the VM is started or stopped. - - Set to (true) with I(state=present) to start the VM. + - Set to C(true) with I(state=present) to start the VM. - Set to C(false) to stop the VM. type: bool + force: + description: + - Use more force during stop of VM + - Set to C(true) with I(started=false) to stop the VM forcefully (hard poweroff -- skip_shutdown) + - Set to C(false) to power off gracefully + default: false + type: bool allocated: description: - Whether the VM is allocated or deallocated, only useful with I(state=present). @@ -76,19 +87,23 @@ options: location: description: - Valid Azure location for the VM. Defaults to location of the resource group. + type: str short_hostname: description: - Name assigned internally to the host. On a Linux VM this is the name returned by the C(hostname) command. - When creating a VM, short_hostname defaults to I(name). + type: str vm_size: description: - A valid Azure VM size value. For example, C(Standard_D4). - Choices vary depending on the subscription and location. Check your subscription for available choices. - Required when creating a VM. + type: str priority: description: - Priority of the VM. - C(None) is the equivalent of Regular VM. + type: str choices: - None - Spot @@ -96,6 +111,7 @@ options: description: - Specifies the eviction policy for the Azure Spot virtual machine. - Requires priority to be set to Spot. + type: str choices: - Deallocate - Delete @@ -105,15 +121,18 @@ options: - This price is in US Dollars. - C(-1) indicates default price to be up-to on-demand. - Requires priority to be set to Spot. + type: float default: -1 admin_username: description: - Admin username used to access the VM after it is created. - Required when creating a VM. + type: str admin_password: description: - Password for the admin username. - Not required if the I(os_type=Linux) and SSH password authentication is disabled by setting I(ssh_password_enabled=false). + type: str ssh_password_enabled: description: - Whether to enable or disable SSH passwords. @@ -126,16 +145,20 @@ options: - Accepts a list of dicts where each dictionary contains two keys, I(path) and I(key_data). - Set I(path) to the default location of the authorized_keys files. For example, I(path=/home/<admin username>/.ssh/authorized_keys). - Set I(key_data) to the actual value of the public key. + type: list + elements: dict image: description: - The image used to build the VM. - For custom images, the name of the image. To narrow the search to a specific resource group, a dict with the keys I(name) and I(resource_group). - For Marketplace images, a dict with the keys I(publisher), I(offer), I(sku), and I(version). - Set I(version=latest) to get the most recent version of a given image. - required: true + - Required when creating. + type: raw availability_set: 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 proximity_placement_group: description: - The name or ID of the proximity placement group the VM should be associated with. @@ -157,6 +180,7 @@ options: description: - Name of a storage account that supports creation of VHD blobs. - If not specified for a new VM, a new storage account named <vm name>01 will be created using storage type C(Standard_LRS). + type: str aliases: - storage_account storage_container_name: @@ -164,6 +188,7 @@ options: - Name of the container to use within the storage account to store VHD blobs. - If not specified, a default container will be created. default: vhds + type: str aliases: - storage_container storage_blob_name: @@ -171,6 +196,7 @@ options: - Name of the storage blob used to hold the OS disk image of the VM. - Must end with '.vhd'. - If not specified, defaults to the VM name + '.vhd'. + type: str aliases: - storage_blob managed_disk_type: @@ -178,6 +204,7 @@ options: - Managed OS disk type. - Create OS disk with managed disk if defined. - If not defined, the OS disk will be created with virtual hard disk (VHD). + type: str choices: - Standard_LRS - StandardSSD_LRS @@ -188,9 +215,11 @@ options: os_disk_name: description: - OS disk name. + type: str os_disk_caching: description: - Type of OS disk caching. + type: str choices: - ReadOnly - ReadWrite @@ -199,9 +228,11 @@ options: os_disk_size_gb: description: - Size of OS disk in GB. + type: int os_type: description: - Base type of operating system. + type: str choices: - Windows - Linux @@ -215,22 +246,27 @@ options: description: - Describes list of data disks. - Use M(azure.azcollection.azure_rm_mangeddisk) to manage the specific disk. + type: list + elements: dict suboptions: lun: description: - The logical unit number for data disk. - This value is used to identify data disks within the VM and therefore must be unique for each data disk attached to a VM. required: true + type: int disk_size_gb: description: - The initial disk size in GB for blank data disks. - This value cannot be larger than C(1023) GB. - Size can be changed only when the virtual machine is deallocated. - Not sure when I(managed_disk_id) defined. + type: int managed_disk_type: description: - Managed data disk type. - Only used when OS disk created with managed disk. + type: str choices: - Standard_LRS - StandardSSD_LRS @@ -245,6 +281,7 @@ options: - Only used when OS disk created with virtual hard disk (VHD). - Used when I(managed_disk_type) not defined. - Cannot be updated unless I(lun) updated. + type: str storage_container_name: description: - Name of the container to use within the storage account to store VHD blobs. @@ -252,6 +289,7 @@ options: - Only used when OS disk created with virtual hard disk (VHD). - Used when I(managed_disk_type) not defined. - Cannot be updated unless I(lun) updated. + type: str default: vhds storage_blob_name: description: @@ -261,19 +299,21 @@ options: - Only used when OS disk created with virtual hard disk (VHD). - Used when I(managed_disk_type) not defined. - Cannot be updated unless I(lun) updated. + type: str caching: description: - Type of data disk caching. + type: str choices: - ReadOnly - ReadWrite - default: ReadOnly public_ip_allocation_method: description: - Allocation method for the public IP of the VM. - Used only if a network interface is not specified. - When set to C(Dynamic), the public IP address may change any time the VM is rebooted or power cycled. - The C(Disabled) choice was added in Ansible 2.6. + type: str choices: - Dynamic - Static @@ -286,6 +326,8 @@ options: - List of ports to open in the security group for the VM, when a security group and network interface are created with a VM. - For Linux hosts, defaults to allowing inbound TCP connections to port 22. - For Windows hosts, defaults to opening ports 3389 and 5986. + type: list + elements: str network_interface_names: description: - Network interface names to add to the VM. @@ -294,16 +336,19 @@ options: - If a network interface name is not provided when the VM is created, a default network interface will be created. - To create a new network interface, at least one Virtual Network with one Subnet must exist. type: list + elements: raw aliases: - network_interfaces virtual_network_resource_group: description: - The resource group to use when creating a VM with another resource group's virtual network. + type: str virtual_network_name: description: - The virtual network to use when creating a VM. - If not specified, a new network interface will be created and assigned to the first virtual network found in the resource group. - Use with I(virtual_network_resource_group) to place the virtual network in another resource group. + type: str aliases: - virtual_network subnet_name: @@ -311,6 +356,7 @@ options: - Subnet for the VM. - Defaults to the first subnet found in the virtual network or the subnet of the I(network_interface_name), if provided. - If the subnet is in another resource group, specify the resource group with I(virtual_network_resource_group). + type: str aliases: - subnet created_nsg: @@ -318,7 +364,7 @@ options: - Whether network security group created and attached to network interface or not. type: bool default: True - version_added: '1.15.0' + version_added: '1.16.0' remove_on_absent: description: - Associated resources to remove when removing a VM using I(state=absent). @@ -327,6 +373,7 @@ options: - To remove only specific resources, set to C(network_interfaces), C(virtual_storage) or C(public_ips). - Any other input will be ignored. type: list + elements: str default: ['all'] plan: description: @@ -337,17 +384,21 @@ options: description: - Billing plan name. required: true + type: str product: description: - Product name. required: true + type: str publisher: description: - Publisher offering the plan. required: true + type: str promotion_code: description: - Optional promotion code. + type: str accept_terms: description: - Accept terms for Marketplace images that require it. @@ -359,11 +410,13 @@ options: description: - A list of Availability Zones for your VM. type: list + elements: str license_type: description: - On-premise license for the image or disk. - Only used for images that contain the Windows Server operating system. - To remove all license type settings, set to the string C(None). + type: str choices: - Windows_Server - Windows_Client @@ -372,30 +425,67 @@ options: vm_identity: description: - Identity for the VM. - choices: - - SystemAssigned + type: dict + suboptions: + type: + description: + - Type of the managed identity + required: true + choices: + - SystemAssigned + - UserAssigned + - SystemAssigned, UserAssigned + - 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: [] + 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 winrm: description: - List of Windows Remote Management configurations of the VM. + type: list + elements: dict suboptions: protocol: description: - The protocol of the winrm listener. required: true + type: str choices: - http - https source_vault: description: - The relative URL of the Key Vault containing the certificate. + type: str certificate_url: description: - The URL of a certificate that has been uploaded to Key Vault as a secret. + type: str certificate_store: description: - The certificate store on the VM to which the certificate should be added. - The specified certificate store is implicitly in the LocalMachine account. + type: str boot_diagnostics: + type: dict description: - Manage boot diagnostics settings for a VM. - Boot diagnostics includes a serial console and remote console screenshots. @@ -403,21 +493,32 @@ options: enabled: description: - Flag indicating if boot diagnostics are enabled. - required: true type: bool + type: + description: + - Should the storage account be managed by azure or a custom storage account + - It is mutually exclusive with suboption I(storage_account) and I(resource_group) + required: false + type: str + choices: + - managed storage_account: description: - The name of an existing storage account to use for boot diagnostics. - If not specified, uses I(storage_account_name) defined one level up. - If storage account is not specified anywhere, and C(enabled) is C(true), a default storage account is created for boot diagnostics data. + - It is mutually exclusive with I(type) + type: str required: false resource_group: description: - Resource group where the storage account is located. + - It is mutually exclusive with I(type) type: str linux_config: description: - Specifies the Linux operating system settings on the virtual machine. + type: dict suboptions: disable_password_authentication: description: @@ -426,6 +527,7 @@ options: windows_config: description: - Specifies Windows operating system settings on the virtual machine. + type: dict suboptions: provision_vm_agent: description: @@ -567,7 +669,8 @@ EXAMPLES = ''' storage_container: osdisk storage_blob: osdisk.vhd boot_diagnostics: - enabled: yes + enabled: true + type: managed image: offer: 0001-com-ubuntu-server-focal publisher: canonical @@ -661,13 +764,13 @@ EXAMPLES = ''' azure_rm_virtualmachine: resource_group: myResourceGroup name: testvm002 - started: no + started: false - name: Deallocate azure_rm_virtualmachine: resource_group: myResourceGroup name: testvm002 - allocated: no + allocated: false - name: Power On azure_rm_virtualmachine: @@ -678,7 +781,7 @@ EXAMPLES = ''' azure_rm_virtualmachine: resource_group: myResourceGroup name: testvm002 - restarted: yes + restarted: true - name: Create a VM with an Availability Zone azure_rm_virtualmachine: @@ -700,9 +803,9 @@ EXAMPLES = ''' admin_password: "{{ password }}" security_profile: uefi_settings: - secure_boot_enabled: True - v_tpm_enabled: True - encryption_at_host: True + secure_boot_enabled: true + v_tpm_enabled: true + encryption_at_host: true security_type: TrustedLaunch ssh_public_keys: - path: /home/azureuser/.ssh/authorized_keys @@ -855,7 +958,7 @@ azure_vm: "adminUsername": "chouseknecht", "computerName": "test10", "linuxConfiguration": { - "disablePasswordAuthentication": false + "disable_password_authentication": false }, "secrets": [] }, @@ -902,9 +1005,8 @@ import time try: from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from msrestazure.azure_exceptions import CloudError from azure.core.exceptions import ResourceNotFoundError - from msrestazure.tools import parse_resource_id + from azure.mgmt.core.tools import parse_resource_id except ImportError: # This is handled in azure_rm_common pass @@ -949,6 +1051,16 @@ linux_configuration_spec = dict( disable_password_authentication=dict(type='bool') ) +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'], required=True), + user_assigned_identities=dict(type='dict', options=user_assigned_identities_spec, default={}), +) + class AzureRMVirtualMachine(AzureRMModuleBase): @@ -968,7 +1080,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase): admin_username=dict(type='str'), admin_password=dict(type='str', no_log=True), ssh_password_enabled=dict(type='bool', default=True, no_log=False), - ssh_public_keys=dict(type='list'), + ssh_public_keys=dict(type='list', elements='dict'), image=dict(type='raw'), availability_set=dict(type='str'), storage_account_name=dict(type='str', aliases=['storage_account']), @@ -982,9 +1094,9 @@ class AzureRMVirtualMachine(AzureRMModuleBase): 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']), - open_ports=dict(type='list'), + open_ports=dict(type='list', elements='str'), network_interface_names=dict(type='list', aliases=['network_interfaces'], elements='raw'), - remove_on_absent=dict(type='list', default=['all']), + remove_on_absent=dict(type='list', default=['all'], elements='str'), virtual_network_resource_group=dict(type='str'), virtual_network_name=dict(type='str', aliases=['virtual_network']), subnet_name=dict(type='str', aliases=['subnet']), @@ -992,15 +1104,47 @@ class AzureRMVirtualMachine(AzureRMModuleBase): allocated=dict(type='bool', default=True), restarted=dict(type='bool', default=False), started=dict(type='bool'), + force=dict(type='bool', default=False), generalized=dict(type='bool', default=False), - data_disks=dict(type='list'), + data_disks=dict( + type='list', + elements='dict', + options=dict( + lun=dict(type='int', required=True), + disk_size_gb=dict(type='int'), + managed_disk_type=dict(type='str', choices=['Standard_LRS', 'StandardSSD_LRS', + 'StandardSSD_ZRS', 'Premium_LRS', 'Premium_ZRS', 'UltraSSD_LRS']), + storage_account_name=dict(type='str'), + storage_container_name=dict(type='str', default='vhds'), + storage_blob_name=dict(type='str'), + caching=dict(type='str', choices=['ReadOnly', 'ReadOnly']) + ) + ), plan=dict(type='dict'), - zones=dict(type='list'), + zones=dict(type='list', elements='str'), accept_terms=dict(type='bool', default=False), license_type=dict(type='str', choices=['Windows_Server', 'Windows_Client', 'RHEL_BYOS', 'SLES_BYOS']), - vm_identity=dict(type='str', choices=['SystemAssigned']), - winrm=dict(type='list'), - boot_diagnostics=dict(type='dict'), + vm_identity=dict(type='dict', options=managed_identity_spec), + winrm=dict( + type='list', + elements='dict', + options=dict( + protocol=dict(type='str', required=True, choices=['http', 'https']), + source_vault=dict(type='str'), + certificate_url=dict(type='str'), + certificate_store=dict(type='str') + ) + ), + boot_diagnostics=dict( + type='dict', + options=dict( + enabled=dict(type='bool'), + type=dict(type='str', choices=['managed']), + storage_account=dict(type='str'), + resource_group=dict(type='str'), + ), + mutually_exclusive=[('type', 'storage_account'), ('type', 'resource_group')], + ), ephemeral_os_disk=dict(type='bool'), windows_config=dict(type='dict', options=windows_configuration_spec), linux_config=dict(type='dict', options=linux_configuration_spec), @@ -1070,7 +1214,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase): @property def boot_diagnostics_present(self): - return self.boot_diagnostics is not None and 'enabled' in self.boot_diagnostics + return self.boot_diagnostics is not None and self.boot_diagnostics.get('enabled') is not None def get_boot_diagnostics_storage_account(self, limited=False, vm_dict=None): """ @@ -1095,8 +1239,8 @@ class AzureRMVirtualMachine(AzureRMModuleBase): - if not there, None """ bsa = None - if 'storage_account' in self.boot_diagnostics: - if 'resource_group' in self.boot_diagnostics: + if self.boot_diagnostics is not None and self.boot_diagnostics.get('storage_account') is not None: + if self.boot_diagnostics.get('resource_group') is not None: bsa = self.get_storage_account(self.boot_diagnostics['resource_group'], self.boot_diagnostics['storage_account']) else: bsa = self.get_storage_account(self.resource_group, self.boot_diagnostics['storage_account']) @@ -1235,18 +1379,18 @@ class AzureRMVirtualMachine(AzureRMModuleBase): differences = [] current_nics = [] results = vm_dict - current_osdisk = vm_dict['properties']['storageProfile']['osDisk'] - current_ephemeral = current_osdisk.get('diffDiskSettings', None) - current_properties = vm_dict['properties'] + current_osdisk = vm_dict['storage_profile']['os_disk'] + current_ephemeral = current_osdisk.get('diff_disk_ettings', None) + current_properties = vm_dict if self.priority and self.priority != current_properties.get('priority', 'None'): self.fail('VM Priority is not updatable: requested virtual machine priority is {0}'.format(self.priority)) if self.eviction_policy and \ - self.eviction_policy != current_properties.get('evictionPolicy', None): + self.eviction_policy != current_properties.get('eviction_policy', None): self.fail('VM Eviction Policy is not updatable: requested virtual machine eviction policy is {0}'.format(self.eviction_policy)) if self.max_price and \ - vm_dict['properties'].get('billingProfile', None) and \ - self.max_price != vm_dict['properties']['billingProfile'].get('maxPrice', None): + vm_dict.get('billing_profile', None) and \ + self.max_price != vm_dict['billing_profile'].get('max_price', None): self.fail('VM Maximum Price is not updatable: requested virtual machine maximum price is {0}'.format(self.max_price)) if self.ephemeral_os_disk and current_ephemeral is None: @@ -1256,7 +1400,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase): # Try to determine if the VM needs to be updated if self.network_interface_names: - for nic in vm_dict['properties']['networkProfile']['networkInterfaces']: + for nic in vm_dict['network_profile']['network_interfaces']: current_nics.append(nic['id']) if set(current_nics) != set(network_interfaces): @@ -1264,47 +1408,47 @@ class AzureRMVirtualMachine(AzureRMModuleBase): differences.append('Network Interfaces') updated_nics = [dict(id=id, primary=(i == 0)) for i, id in enumerate(network_interfaces)] - vm_dict['properties']['networkProfile']['networkInterfaces'] = updated_nics + vm_dict['network_profile']['network_interfaces'] = updated_nics changed = True if self.os_disk_caching and \ - self.os_disk_caching != vm_dict['properties']['storageProfile']['osDisk']['caching']: + self.os_disk_caching != vm_dict['storage_profile']['os_disk']['caching']: self.log('CHANGED: virtual machine {0} - OS disk caching'.format(self.name)) differences.append('OS Disk caching') changed = True - vm_dict['properties']['storageProfile']['osDisk']['caching'] = self.os_disk_caching + vm_dict['storage_profile']['os_disk']['caching'] = self.os_disk_caching if self.os_disk_name and \ - self.os_disk_name != vm_dict['properties']['storageProfile']['osDisk']['name']: + self.os_disk_name != vm_dict['storage_profile']['os_disk']['name']: self.log('CHANGED: virtual machine {0} - OS disk name'.format(self.name)) differences.append('OS Disk name') changed = True - vm_dict['properties']['storageProfile']['osDisk']['name'] = self.os_disk_name + vm_dict['storage_profile']['os_disk']['name'] = self.os_disk_name if self.os_disk_size_gb and \ - self.os_disk_size_gb != vm_dict['properties']['storageProfile']['osDisk'].get('diskSizeGB'): + self.os_disk_size_gb != vm_dict['storage_profile']['os_disk'].get('disk_size_gb'): self.log('CHANGED: virtual machine {0} - OS disk size '.format(self.name)) differences.append('OS Disk size') changed = True - vm_dict['properties']['storageProfile']['osDisk']['diskSizeGB'] = self.os_disk_size_gb + vm_dict['storage_profile']['os_disk']['disk_size_gb'] = self.os_disk_size_gb if self.vm_size and \ - self.vm_size != vm_dict['properties']['hardwareProfile']['vmSize']: + self.vm_size != vm_dict['hardware_profile']['vm_size']: self.log('CHANGED: virtual machine {0} - size '.format(self.name)) differences.append('VM size') changed = True - vm_dict['properties']['hardwareProfile']['vmSize'] = self.vm_size + vm_dict['hardware_profile']['vm_size'] = self.vm_size update_tags, vm_dict['tags'] = self.update_tags(vm_dict.get('tags', dict())) if update_tags: differences.append('Tags') changed = True - if self.short_hostname and self.short_hostname != vm_dict['properties']['osProfile']['computerName']: + if self.short_hostname and self.short_hostname != vm_dict['os_profile']['computer_name']: self.log('CHANGED: virtual machine {0} - short hostname'.format(self.name)) differences.append('Short Hostname') changed = True - vm_dict['properties']['osProfile']['computerName'] = self.short_hostname + vm_dict['os_orofile']['computer_name'] = self.short_hostname if self.started and vm_dict['powerstate'] not in ['starting', 'running'] and self.allocated: self.log("CHANGED: virtual machine {0} not running and requested state 'running'".format(self.name)) @@ -1335,74 +1479,108 @@ class AzureRMVirtualMachine(AzureRMModuleBase): differences.append('Zones') changed = True - if self.license_type is not None and vm_dict['properties'].get('licenseType') != self.license_type: + if self.license_type is not None and vm_dict.get('licenseType') != self.license_type: differences.append('License Type') changed = True + if self.vm_identity: + update_vm_identity = False + # If type set to None, and VM has no current identities, nothing to do + if 'None' in self.vm_identity.get('type') and 'identity' not in vm_dict: + pass + # If type different to None, and VM has no current identities, update identities + elif 'identity' not in vm_dict: + update_vm_identity = True + # If type in module args different from type of vm_dict, update identities + elif vm_dict['identity']['type'] != self.vm_identity.get('type'): + update_vm_identity = True + # If type in module args contains 'UserAssigned' + elif 'UserAssigned' in self.vm_identity.get('type'): + # Create sets with current user identities and module args identities + new_managed_identities = set(self.vm_identity.get('user_assigned_identities', {}).get('id', [])) + current_managed_identities = set(vm_dict['identity']['user_assigned_identities'].keys()) + # If new identities have to be appended to VM + if self.vm_identity.get('user_assigned_identities', {}).get('append', False) is True: + # and the union of identities is longer + if len(current_managed_identities) != len(new_managed_identities.union(current_managed_identities)): + # update identities + update_vm_identity = 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(new_managed_identities) != set(): + update_vm_identity = True + if update_vm_identity: + differences.append('Managed Identities') + changed = True + if self.security_profile is not None: update_security_profile = False - if 'securityProfile' not in vm_dict['properties'].keys(): + if 'securityProfile' not in vm_dict.keys(): update_security_profile = True differences.append('security_profile') else: if self.security_profile.get('encryption_at_host') is not None: - if bool(self.security_profile.get('encryption_at_host')) != bool(vm_dict['properties']['securityProfile']['encryptionAtHost']): - update_security_profle = True + if bool(self.security_profile.get('encryption_at_host')) != bool(vm_dict['security_profile']['encryption_at_host']): + update_security_profile = True else: - self.security_profile['encryption_at_host'] = vm_dict['properties']['securityProfile']['encryptionAtHost'] + self.security_profile['encryption_at_host'] = vm_dict['security_profile']['encryption_at_host'] if self.security_profile.get('security_type') is not None: - if self.security_profile.get('security_type') != vm_dict['properties']['securityProfile']['securityType']: + if self.security_profile.get('security_type') != vm_dict['security_profile']['security_type']: update_security_profile = True if self.security_profile.get('uefi_settings') is not None: if self.security_profile['uefi_settings'].get('secure_boot_enabled') is not None: if bool(self.security_profile['uefi_settings']['secure_boot_enabled']) != \ - bool(vm_dict['properties']['securityProfile']['uefiSettings']['secureBootEnabled']): + bool(vm_dict['security_profile']['uefi_settings']['secure_boot_enabled']): update_security_profile = True else: self.security_profile['uefi_settings']['secure_boot_enabled'] = \ - vm_dict['properties']['securityProfile']['uefiSettings']['secureBootEnabled'] + vm_dict['security_profile']['uefi_settings']['secure_soot_enabled'] if self.security_profile['uefi_settings'].get('v_tpm_enabled') is not None: if bool(self.security_profile['uefi_settings']['v_tpm_enabled']) != \ - bool(vm_dict['properties']['securityProfile']['uefiSettings']['vTpmEnabled']): + bool(vm_dict['security_profile']['uefi_settings']['v_tpm_enabled']): update_security_profile = True else: self.security_profile['uefi_settings']['v_tpm_enabled'] = \ - vm_dict['properties']['securityProfile']['uefiSettings']['vTpmEnabled'] - if update_security_profile: - changed = True - differences.append('security_profile') + vm_dict['security_profile']['uefi_settings']['v_tpm_enabled'] + if update_security_profile: + changed = True + differences.append('security_profile') - if self.windows_config is not None and vm_dict['properties']['osProfile'].get('windowsConfiguration') is not None: - if self.windows_config['enable_automatic_updates'] != vm_dict['properties']['osProfile']['windowsConfiguration']['enableAutomaticUpdates']: + if self.windows_config is not None and vm_dict['os_profile'].get('windows_configuration') is not None: + if self.windows_config['enable_automatic_updates'] != vm_dict['os_profile']['windows_configuration']['enable_automatic_updates']: self.fail("(PropertyChangeNotAllowed) Changing property 'windowsConfiguration.enableAutomaticUpdates' is not allowed.") - if self.windows_config['provision_vm_agent'] != vm_dict['properties']['osProfile']['windowsConfiguration']['provisionVMAgent']: + if self.windows_config['provision_vm_agent'] != vm_dict['os_profile']['windows_configuration']['provision_vm_agent']: self.fail("(PropertyChangeNotAllowed) Changing property 'windowsConfiguration.provisionVMAgent' is not allowed.") - if self.linux_config is not None and vm_dict['properties']['osProfile'].get('linuxConfiguration') is not None: + if self.linux_config is not None and vm_dict['os_profile'].get('linux_configuration') is not None: if self.linux_config['disable_password_authentication'] != \ - vm_dict['properties']['osProfile']['linuxConfiguration']['disablePasswordAuthentication']: + vm_dict['os_profile']['linux_configuration']['disable_password_authentication']: self.fail("(PropertyChangeNotAllowed) Changing property 'linuxConfiguration.disablePasswordAuthentication' is not allowed.") # Defaults for boot diagnostics - if 'diagnosticsProfile' not in vm_dict['properties']: - vm_dict['properties']['diagnosticsProfile'] = {} - if 'bootDiagnostics' not in vm_dict['properties']['diagnosticsProfile']: - vm_dict['properties']['diagnosticsProfile']['bootDiagnostics'] = { + if 'diagnostics_profile' not in vm_dict: + vm_dict['diagnostics_profile'] = {} + if 'boot_diagnostics' not in vm_dict['diagnostics_profile']: + vm_dict['diagnostics_profile']['boot_diagnostics'] = { 'enabled': False, 'storageUri': None } if self.boot_diagnostics_present: - current_boot_diagnostics = vm_dict['properties']['diagnosticsProfile']['bootDiagnostics'] + current_boot_diagnostics = vm_dict['diagnostics_profile']['boot_diagnostics'] boot_diagnostics_changed = False if self.boot_diagnostics['enabled'] != current_boot_diagnostics['enabled']: current_boot_diagnostics['enabled'] = self.boot_diagnostics['enabled'] boot_diagnostics_changed = True - boot_diagnostics_storage_account = self.get_boot_diagnostics_storage_account( - limited=not self.boot_diagnostics['enabled'], vm_dict=vm_dict) - boot_diagnostics_blob = boot_diagnostics_storage_account.primary_endpoints.blob if boot_diagnostics_storage_account else None + if self.boot_diagnostics.get('type') is not None and self.boot_diagnostics['type'] == 'managed': + boot_diagnostics_blob = None + else: + boot_diagnostics_storage_account = self.get_boot_diagnostics_storage_account( + limited=not self.boot_diagnostics['enabled'], vm_dict=vm_dict) + boot_diagnostics_blob = boot_diagnostics_storage_account.primary_endpoints.blob if boot_diagnostics_storage_account else None if current_boot_diagnostics.get('storageUri') != boot_diagnostics_blob: current_boot_diagnostics['storageUri'] = boot_diagnostics_blob boot_diagnostics_changed = True @@ -1529,7 +1707,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase): promotion_code=self.plan.get('promotion_code')) # do this before creating vm_resource as it can modify tags - if self.boot_diagnostics_present and self.boot_diagnostics['enabled']: + if self.boot_diagnostics_present and self.boot_diagnostics['enabled'] and self.boot_diagnostics.get('type') != 'managed': boot_diag_storage_account = self.get_boot_diagnostics_storage_account() vm_resource = self.compute_models.VirtualMachine( @@ -1574,7 +1752,22 @@ class AzureRMVirtualMachine(AzureRMModuleBase): vm_resource.license_type = self.license_type if self.vm_identity: - vm_resource.identity = self.compute_models.VirtualMachineIdentity(type=self.vm_identity) + # If UserAssigned in module args and ids specified + if 'UserAssigned' in self.vm_identity.get('type') and len(self.vm_identity.get('user_assigned_identities', {}).get('id', [])) != 0: + user_assigned_identities_dict = {uami: dict() for uami in self.vm_identity.get('user_assigned_identities').get('id')} + # Append identities to the model + vm_resource.identity = self.compute_models.VirtualMachineIdentity( + type=self.vm_identity.get('type'), + user_assigned_identities=user_assigned_identities_dict + ) + # If UserAssigned in module args, but ids are not specified + elif 'UserAssigned' in self.vm_identity.get('type') and len(self.vm_identity.get('user_assigned_identities', {}).get('id', [])) == 0: + self.fail("UserAssigned specified but no User Identity IDs provided") + # In any other case ('SystemAssigned' or 'None') apply the configuration to the model + else: + vm_resource.identity = self.compute_models.VirtualMachineIdentity( + type=self.vm_identity.get('type') + ) if self.winrm: winrm_listeners = list() @@ -1611,7 +1804,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase): ) if self.boot_diagnostics_present: - if self.boot_diagnostics['enabled']: + if self.boot_diagnostics['enabled'] and self.boot_diagnostics.get('type') != 'managed': storage_uri = boot_diag_storage_account.primary_endpoints.blob else: storage_uri = None @@ -1732,43 +1925,43 @@ class AzureRMVirtualMachine(AzureRMModuleBase): self.log("Update virtual machine {0}".format(self.name)) self.results['actions'].append('Updated VM {0}'.format(self.name)) nics = [self.compute_models.NetworkInterfaceReference(id=interface['id'], primary=(i == 0)) - for i, interface in enumerate(vm_dict['properties']['networkProfile']['networkInterfaces'])] + for i, interface in enumerate(vm_dict['network_profile']['network_interfaces'])] # os disk - if not vm_dict['properties']['storageProfile']['osDisk'].get('managedDisk'): + if not vm_dict['storage_profile']['os_disk'].get('managedDisk'): managed_disk = None - vhd = self.compute_models.VirtualHardDisk(uri=vm_dict['properties']['storageProfile']['osDisk'].get('vhd', {}).get('uri')) + vhd = self.compute_models.VirtualHardDisk(uri=vm_dict['storage_profile']['os_disk'].get('vhd', {}).get('uri')) else: vhd = None managed_disk = self.compute_models.ManagedDiskParameters( - storage_account_type=vm_dict['properties']['storageProfile']['osDisk']['managedDisk'].get('storageAccountType') + storage_account_type=vm_dict['storage_profile']['os_disk']['managed_disk'].get('storage_account_type') ) proximity_placement_group_resource = None try: - proximity_placement_group_resource = self.compute_models.SubResource(id=vm_dict['properties']['proximityPlacementGroup'].get('id')) + proximity_placement_group_resource = self.compute_models.SubResource(id=vm_dict['proximity_placement_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['properties']['availabilitySet'].get('id')) + availability_set_resource = self.compute_models.SubResource(id=vm_dict['availability_set'].get('id')) except Exception: # pass if the availability set is not set pass - if 'imageReference' in vm_dict['properties']['storageProfile'].keys(): - if 'id' in vm_dict['properties']['storageProfile']['imageReference'].keys(): + if 'imageReference' in vm_dict['storage_profile'].keys(): + if 'id' in vm_dict['storage_profile']['image_reference'].keys(): image_reference = self.compute_models.ImageReference( - id=vm_dict['properties']['storageProfile']['imageReference']['id'] + id=vm_dict['storage_profile']['image_reference']['id'] ) else: image_reference = self.compute_models.ImageReference( - publisher=vm_dict['properties']['storageProfile']['imageReference'].get('publisher'), - offer=vm_dict['properties']['storageProfile']['imageReference'].get('offer'), - sku=vm_dict['properties']['storageProfile']['imageReference'].get('sku'), - version=vm_dict['properties']['storageProfile']['imageReference'].get('version') + publisher=vm_dict['storage_profile']['image_reference'].get('publisher'), + offer=vm_dict['storage_profile']['image_reference'].get('offer'), + sku=vm_dict['storage_profile']['image_reference'].get('sku'), + version=vm_dict['storage_profile']['image_reference'].get('version') ) else: image_reference = None @@ -1777,10 +1970,10 @@ class AzureRMVirtualMachine(AzureRMModuleBase): if self.zones is not None and vm_dict['zones'] != self.zones: self.fail("You can't change the Availability Zone of a virtual machine (have: {0}, want: {1})".format(vm_dict['zones'], self.zones)) - if 'osProfile' in vm_dict['properties']: + if 'os_profile' in vm_dict: os_profile = self.compute_models.OSProfile( - admin_username=vm_dict['properties'].get('osProfile', {}).get('adminUsername'), - computer_name=vm_dict['properties'].get('osProfile', {}).get('computerName') + admin_username=vm_dict.get('os_profile', {}).get('admin_username'), + computer_name=vm_dict.get('os_profile', {}).get('computer_name') ) else: os_profile = None @@ -1789,17 +1982,17 @@ class AzureRMVirtualMachine(AzureRMModuleBase): location=vm_dict['location'], os_profile=os_profile, hardware_profile=self.compute_models.HardwareProfile( - vm_size=vm_dict['properties']['hardwareProfile'].get('vmSize') + vm_size=vm_dict['hardware_profile'].get('vm_size') ), storage_profile=self.compute_models.StorageProfile( os_disk=self.compute_models.OSDisk( - name=vm_dict['properties']['storageProfile']['osDisk'].get('name'), + name=vm_dict['storage_profile']['os_disk'].get('name'), vhd=vhd, managed_disk=managed_disk, - create_option=vm_dict['properties']['storageProfile']['osDisk'].get('createOption'), - os_type=vm_dict['properties']['storageProfile']['osDisk'].get('osType'), - caching=vm_dict['properties']['storageProfile']['osDisk'].get('caching'), - disk_size_gb=vm_dict['properties']['storageProfile']['osDisk'].get('diskSizeGB') + create_option=vm_dict['storage_profile']['os_disk'].get('create_option'), + os_type=vm_dict['storage_profile']['os_disk'].get('os_type'), + caching=vm_dict['storage_profile']['os_disk'].get('caching'), + disk_size_gb=vm_dict['storage_profile']['os_disk'].get('disk_size_gb') ), image_reference=image_reference ), @@ -1813,27 +2006,75 @@ class AzureRMVirtualMachine(AzureRMModuleBase): if self.license_type is not None: vm_resource.license_type = self.license_type + if self.vm_identity is not None: + # If 'append' is set to True save current user assigned managed identities to use later + if (self.vm_identity.get('user_assigned_identities', {}) is not None + and self.vm_identity.get('user_assigned_identities', {}).get('append', False) is True): + if 'identity' in vm_dict and 'user_assigned_identities' in vm_dict['identity']: + current_user_assigned_identities_dict = {uami: dict() for uami in vm_dict['identity']['user_assigned_identities'].keys()} + vm_identity_user_assigned_append = True + else: + # Nothing to append to + vm_identity_user_assigned_append = False + else: + # 'append' is False or unset + vm_identity_user_assigned_append = False + # If there are identities in 'id' and 'UserAssigned' in type + if 'UserAssigned' in self.vm_identity.get('type') and len(self.vm_identity.get('user_assigned_identities', {}).get('id', [])) != 0: + user_assigned_identities_dict = {uami: dict() for uami in self.vm_identity.get('user_assigned_identities').get('id')} + # If there are identities to append, merge the dicts + if vm_identity_user_assigned_append: + user_assigned_identities_dict = {**user_assigned_identities_dict, **current_user_assigned_identities_dict} + # Save the identity + vm_resource.identity = self.compute_models.VirtualMachineIdentity( + type=self.vm_identity.get('type'), + user_assigned_identities=user_assigned_identities_dict + ) + # If there are no identities in 'id' and 'UserAssigned' in type + elif 'UserAssigned' in self.vm_identity.get('type') and len(self.vm_identity.get('user_assigned_identities', {}).get('id', [])) == 0: + # Fail if append is False + if vm_identity_user_assigned_append is False: + self.fail("UserAssigned specified but no User Assigned IDs provided" + + " and no UserAssigned identities are currently assigned to the VM") + # If append is true, user is changing from 'UserAssigned' to 'SystemAssigned, UserAssigned' + # and wants to keep current UserAssigned identities + else: + # Save current identities + vm_resource.identity = self.compute_models.VirtualMachineIdentity( + type=self.vm_identity.get('type'), + user_assigned_identities=current_user_assigned_identities_dict + ) + # Set 'SystemAssigned' or 'None' + else: + vm_resource.identity = self.compute_models.VirtualMachineIdentity( + type=self.vm_identity.get('type') + ) + if self.boot_diagnostics is not None: + storage_uri = None + # storageUri is undefined if boot diagnostics is disabled + if 'storageUri' in vm_dict['diagnostics_profile']['boot_diagnostics']: + storage_uri = vm_dict['diagnostics_profile']['boot_diagnostics']['storageUri'] vm_resource.diagnostics_profile = self.compute_models.DiagnosticsProfile( boot_diagnostics=self.compute_models.BootDiagnostics( - enabled=vm_dict['properties']['diagnosticsProfile']['bootDiagnostics']['enabled'], - storage_uri=vm_dict['properties']['diagnosticsProfile']['bootDiagnostics']['storageUri'])) + enabled=vm_dict['diagnostics_profile']['boot_diagnostics']['enabled'], + storage_uri=storage_uri)) if vm_dict.get('tags'): vm_resource.tags = vm_dict['tags'] # Add custom_data, if provided - if vm_dict['properties'].get('osProfile', {}).get('customData'): - custom_data = vm_dict['properties']['osProfile']['customData'] + if vm_dict.get('os_profile', {}).get('custom_data'): + custom_data = vm_dict['os_profile']['custom_data'] # Azure SDK (erroneously?) wants native string type for this vm_resource.os_profile.custom_data = to_native(base64.b64encode(to_bytes(custom_data))) # Add admin password, if one provided - if vm_dict['properties'].get('osProfile', {}).get('adminPassword'): - vm_resource.os_profile.admin_password = vm_dict['properties']['osProfile']['adminPassword'] + if vm_dict.get('os_profile', {}).get('admin_password'): + vm_resource.os_profile.admin_password = vm_dict['os_profile']['admin_password'] # Add Windows configuration, if applicable - windows_config = vm_dict['properties'].get('osProfile', {}).get('windowsConfiguration') + windows_config = vm_dict.get('os_profile', {}).get('windows_configuration') if windows_config: if self.windows_config is not None: vm_resource.os_profile.windows_configuration = self.compute_models.WindowsConfiguration( @@ -1847,7 +2088,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase): ) # Add linux configuration, if applicable - linux_config = vm_dict['properties'].get('osProfile', {}).get('linuxConfiguration') + linux_config = vm_dict.get('os_profile', {}).get('linux_configuration') if linux_config: if self.linux_config is not None: vm_resource.os_profile.linux_configuration = self.compute_models.LinuxConfiguration( @@ -1855,7 +2096,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase): ) else: vm_resource.os_profile.linux_configuration = self.compute_models.LinuxConfiguration( - disable_password_authentication=linux_config.get('disablePasswordAuthentication', False) + disable_password_authentication=linux_config.get('disable_password_authentication', False) ) ssh_config = linux_config.get('ssh', None) if ssh_config: @@ -1868,12 +2109,12 @@ class AzureRMVirtualMachine(AzureRMModuleBase): ) # data disk - if vm_dict['properties']['storageProfile'].get('dataDisks'): + if vm_dict['storage_profile'].get('data_disks'): data_disks = [] - for data_disk in vm_dict['properties']['storageProfile']['dataDisks']: - if data_disk.get('managedDisk'): - managed_disk_type = data_disk['managedDisk'].get('storageAccountType') + for data_disk in vm_dict['storage_profile']['data_disks']: + if data_disk.get('managed_disk'): + managed_disk_type = data_disk['managed_disk'].get('storage_account_type') data_disk_managed_disk = self.compute_models.ManagedDiskParameters(storage_account_type=managed_disk_type) data_disk_vhd = None else: @@ -1885,8 +2126,8 @@ class AzureRMVirtualMachine(AzureRMModuleBase): name=data_disk.get('name'), vhd=data_disk_vhd, caching=data_disk.get('caching'), - create_option=data_disk.get('createOption'), - disk_size_gb=int(data_disk.get('diskSizeGB', 0)) or None, + create_option=data_disk.get('create_option'), + disk_size_gb=int(data_disk.get('disk_size_gb', 0)) or None, managed_disk=data_disk_managed_disk, )) vm_resource.storage_profile.data_disks = data_disks @@ -1980,16 +2221,16 @@ class AzureRMVirtualMachine(AzureRMModuleBase): for interface in vm.network_profile.network_interfaces: int_dict = azure_id_to_dict(interface.id) nic = self.get_network_interface(int_dict['resourceGroups'], int_dict['networkInterfaces']) - for interface_dict in result['properties']['networkProfile']['networkInterfaces']: + for interface_dict in result['network_profile']['network_interfaces']: if interface_dict['id'] == interface.id: nic_dict = self.serialize_obj(nic, 'NetworkInterface') interface_dict['name'] = int_dict['networkInterfaces'] - interface_dict['properties'] = nic_dict['properties'] + interface_dict['properties'] = nic_dict # Expand public IPs to include config properties - for interface in result['properties']['networkProfile']['networkInterfaces']: - for config in interface['properties']['ipConfigurations']: - if config['properties'].get('publicIPAddress'): - pipid_dict = azure_id_to_dict(config['properties']['publicIPAddress']['id']) + for interface in result['network_profile']['network_interfaces']: + for config in interface['properties']['ip_configurations']: + if config.get('public_ip_address'): + pipid_dict = azure_id_to_dict(config['public_ip_address']['id']) try: pip = self.network_client.public_ip_addresses.get(pipid_dict['resourceGroups'], pipid_dict['publicIPAddresses']) @@ -1997,8 +2238,8 @@ class AzureRMVirtualMachine(AzureRMModuleBase): self.fail("Error fetching public ip {0} - {1}".format(pipid_dict['publicIPAddresses'], str(exc))) pip_dict = self.serialize_obj(pip, 'PublicIPAddress') - config['properties']['publicIPAddress']['name'] = pipid_dict['publicIPAddresses'] - config['properties']['publicIPAddress']['properties'] = pip_dict['properties'] + config['public_ip_address']['name'] = pipid_dict['publicIPAddresses'] + config['public_ip_address']['properties'] = pip_dict['ip_configuration'] self.log(result, pretty_print=True) if self.state != 'absent' and not result['powerstate']: @@ -2006,10 +2247,10 @@ class AzureRMVirtualMachine(AzureRMModuleBase): return result def power_off_vm(self): - self.log("Powered off virtual machine {0}".format(self.name)) - self.results['actions'].append("Powered off virtual machine {0}".format(self.name)) + self.log("Powered off virtual machine {0} - Skip_Shutdown {1}".format(self.name, self.force)) + self.results['actions'].append("Powered off virtual machine {0} - Skip_Shutdown {1}".format(self.name, self.force)) try: - poller = self.compute_client.virtual_machines.begin_power_off(self.resource_group, self.name) + poller = self.compute_client.virtual_machines.begin_power_off(self.resource_group, self.name, skip_shutdown=self.force) self.get_poller_result(poller) except Exception as exc: self.fail("Error powering off virtual machine {0} - {1}".format(self.name, str(exc))) @@ -2459,7 +2700,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase): try: subnet = self.network_client.subnets.get(virtual_network_resource_group, virtual_network_name, self.subnet_name) subnet_id = subnet.id - except CloudError as exc: + except Exception as exc: self.fail("Error: fetching subnet {0} - {1}".format(self.subnet_name, str(exc))) else: no_subnets_msg = "Error: unable to find a subnet in virtual network {0}. A virtual network " \ diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachine_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachine_info.py index 50d909c92..d94f9848e 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachine_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachine_info.py @@ -25,9 +25,11 @@ options: resource_group: description: - Name of the resource group containing the virtual machines (required when filtering by vm name). + type: str name: description: - Name of the virtual machine. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -44,21 +46,21 @@ author: ''' EXAMPLES = ''' - - name: Get facts for all virtual machines of a resource group - azure_rm_virtualmachine_info: - resource_group: myResourceGroup - - - name: Get facts by name - azure_rm_virtualmachine_info: - resource_group: myResourceGroup - name: myVm - - - name: Get facts by tags - azure_rm_virtualmachine_info: - resource_group: myResourceGroup - tags: - - testing - - foo:bar +- name: Get facts for all virtual machines of a resource group + azure_rm_virtualmachine_info: + resource_group: myResourceGroup + +- name: Get facts by name + azure_rm_virtualmachine_info: + resource_group: myResourceGroup + name: myVm + +- name: Get facts by tags + azure_rm_virtualmachine_info: + resource_group: myResourceGroup + tags: + - testing + - foo:bar ''' RETURN = ''' @@ -275,44 +277,44 @@ vms: description: - Specifies the Security related profile settings for the virtual machine. type: complex - returned: always + returned: when-used contains: encryption_at_host: description: - This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. - This will enable the encryption for all the disks including Resource/Temp disk at host itself. type: bool - returned: always + returned: when-enabled sample: True security_type: description: - Specifies the SecurityType of the virtual machine. - It is set as TrustedLaunch to enable UefiSettings. type: str - returned: always + returned: when-enabled sample: TrustedLaunch uefi_settings: description: - Specifies the security settings like secure boot and vTPM used while creating the virtual machine. type: complex - returned: always + returned: when-enabled contains: secure_boot_enabled: description: - Specifies whether secure boot should be enabled on the virtual machine. type: bool - returned: always + returned: when-enabled sample: True v_tpm_enabled: description: - Specifies whether vTPM should be enabled on the virtual machine. type: bool - returned: always + returned: when-enabled sample: True ''' try: - from msrestazure.tools import parse_resource_id + from azure.mgmt.core.tools import parse_resource_id from azure.core.exceptions import ResourceNotFoundError except Exception: # This is handled in azure_rm_common @@ -445,13 +447,13 @@ class AzureRMVirtualMachineInfo(AzureRMModuleBase): code = instance['statuses'][index]['code'].split('/') if code[0] == 'PowerState': power_state = code[1] - display_status = instance['statuses'][index]['displayStatus'] + display_status = instance['statuses'][index]['display_status'] elif code[0] == 'OSState' and code[1] == 'generalized': - display_status = instance['statuses'][index]['displayStatus'] + display_status = instance['statuses'][index]['display_status'] power_state = 'generalized' break elif code[0] == 'ProvisioningState' and code[1] == 'failed': - display_status = instance['statuses'][index]['displayStatus'] + display_status = instance['statuses'][index]['display_status'] power_state = '' break @@ -459,11 +461,16 @@ class AzureRMVirtualMachineInfo(AzureRMModuleBase): if vm.security_profile is not None: new_result['security_profile'] = dict() - new_result['security_profile']['encryption_at_host'] = vm.security_profile.encryption_at_host - new_result['security_profile']['security_type'] = vm.security_profile.security_type - new_result['security_profile']['uefi_settings'] = dict() - new_result['security_profile']['uefi_settings']['secure_boot_enabled'] = vm.security_profile.uefi_settings.secure_boot_enabled - new_result['security_profile']['uefi_settings']['v_tpm_enabled'] = vm.security_profile.uefi_settings.v_tpm_enabled + if vm.security_profile.encryption_at_host is not None: + new_result['security_profile']['encryption_at_host'] = vm.security_profile.encryption_at_host + if vm.security_profile.security_type is not None: + new_result['security_profile']['security_type'] = vm.security_profile.security_type + if vm.security_profile.uefi_settings is not None: + new_result['security_profile']['uefi_settings'] = dict() + if vm.security_profile.uefi_settings.secure_boot_enabled is not None: + new_result['security_profile']['uefi_settings']['secure_boot_enabled'] = vm.security_profile.uefi_settings.secure_boot_enabled + if vm.security_profile.uefi_settings.v_tpm_enabled is not None: + new_result['security_profile']['uefi_settings']['v_tpm_enabled'] = vm.security_profile.uefi_settings.v_tpm_enabled new_result['power_state'] = power_state new_result['display_status'] = display_status @@ -473,13 +480,13 @@ class AzureRMVirtualMachineInfo(AzureRMModuleBase): new_result['name'] = vm.name new_result['state'] = 'present' new_result['location'] = vm.location - new_result['vm_size'] = result['properties']['hardwareProfile']['vmSize'] - new_result['proximityPlacementGroup'] = result['properties'].get('proximityPlacementGroup') + new_result['vm_size'] = result['hardware_profile']['vm_size'] + new_result['proximityPlacementGroup'] = result.get('proximity_placement_group') new_result['zones'] = result.get('zones', None) - os_profile = result['properties'].get('osProfile') + os_profile = result.get('os_profile') if os_profile is not None: - new_result['admin_username'] = os_profile.get('adminUsername') - image = result['properties']['storageProfile'].get('imageReference') + new_result['admin_username'] = os_profile.get('admin_username') + image = result['storage_profile'].get('image_reference') if image is not None: if image.get('publisher', None) is not None: new_result['image'] = { @@ -494,40 +501,40 @@ class AzureRMVirtualMachineInfo(AzureRMModuleBase): } new_result['boot_diagnostics'] = { - 'enabled': 'diagnosticsProfile' in result['properties'] and - 'bootDiagnostics' in result['properties']['diagnosticsProfile'] and - result['properties']['diagnosticsProfile']['bootDiagnostics']['enabled'] or False, - 'storage_uri': 'diagnosticsProfile' in result['properties'] and - 'bootDiagnostics' in result['properties']['diagnosticsProfile'] and - result['properties']['diagnosticsProfile']['bootDiagnostics'].get('storageUri', None) + 'enabled': 'diagnostics_profile' in result and + 'boot_diagnostics' in result['diagnostics_profile'] and + result['diagnostics_profile']['boot_diagnostics']['enabled'] or False, + 'storage_uri': 'diagnostics_profile' in result and + 'boot_diagnostics' in result['diagnostics_profile'] and + result['diagnostics_profile']['boot_diagnostics'].get('storageUri', None) } if new_result['boot_diagnostics']['enabled']: - new_result['boot_diagnostics']['console_screenshot_uri'] = result['properties']['instanceView']['bootDiagnostics'].get('consoleScreenshotBlobUri') - new_result['boot_diagnostics']['serial_console_log_uri'] = result['properties']['instanceView']['bootDiagnostics'].get('serialConsoleLogBlobUri') + new_result['boot_diagnostics']['console_screenshot_uri'] = result['instance_view']['boot_diagnostics'].get('console_screenshot_blob_uri') + new_result['boot_diagnostics']['serial_console_log_uri'] = result['instance_view']['boot_diagnostics'].get('serial_console_log_blob_uri') - vhd = result['properties']['storageProfile']['osDisk'].get('vhd') + vhd = result['storage_profile']['os_disk'].get('vhd') if vhd is not None: url = urlparse(vhd['uri']) new_result['storage_account_name'] = url.netloc.split('.')[0] new_result['storage_container_name'] = url.path.split('/')[1] new_result['storage_blob_name'] = url.path.split('/')[-1] - new_result['os_disk_caching'] = result['properties']['storageProfile']['osDisk']['caching'] - new_result['os_type'] = result['properties']['storageProfile']['osDisk']['osType'] + new_result['os_disk_caching'] = result['storage_profile']['os_disk']['caching'] + new_result['os_type'] = result['storage_profile']['os_disk']['os_type'] new_result['data_disks'] = [] - disks = result['properties']['storageProfile']['dataDisks'] + disks = result['storage_profile']['data_disks'] for disk_index in range(len(disks)): new_result['data_disks'].append({ 'lun': disks[disk_index].get('lun'), 'name': disks[disk_index].get('name'), - 'disk_size_gb': disks[disk_index].get('diskSizeGB'), - 'managed_disk_type': disks[disk_index].get('managedDisk', {}).get('storageAccountType'), - 'managed_disk_id': disks[disk_index].get('managedDisk', {}).get('id'), + 'disk_size_gb': disks[disk_index].get('disk_size_gb'), + 'managed_disk_type': disks[disk_index].get('managed_disk', {}).get('storage_account_type'), + 'managed_disk_id': disks[disk_index].get('managed_disk', {}).get('id'), 'caching': disks[disk_index].get('caching') }) new_result['network_interface_names'] = [] - nics = result['properties']['networkProfile']['networkInterfaces'] + nics = result['network_profile']['network_interfaces'] for nic_index in range(len(nics)): new_result['network_interface_names'].append(re.sub('.*networkInterfaces/', '', nics[nic_index]['id'])) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachineextension_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachineextension_info.py index 98f748c2f..f9068d7ae 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachineextension_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachineextension_info.py @@ -46,16 +46,16 @@ author: ''' EXAMPLES = ''' - - name: Get information on specific Virtual Machine Extension - azure_rm_virtualmachineextension_info: - resource_group: myResourceGroup - virtual_machine_name: myvm - name: myextension - - - name: List installed Virtual Machine Extensions - azure_rm_virtualmachineextension_info: - resource_group: myResourceGroup - virtual_machine_name: myvm +- name: Get information on specific Virtual Machine Extension + azure_rm_virtualmachineextension_info: + resource_group: myResourceGroup + virtual_machine_name: myvm + name: myextension + +- name: List installed Virtual Machine Extensions + azure_rm_virtualmachineextension_info: + resource_group: myResourceGroup + virtual_machine_name: myvm ''' RETURN = ''' @@ -138,7 +138,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachineimage_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachineimage_info.py index fc18f2dd2..9d314ef91 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachineimage_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachineimage_info.py @@ -26,18 +26,23 @@ options: - Azure location value, for example C(westus), C(eastus), C(eastus2), C(northcentralus), etc. - Supplying only a location value will yield a list of available publishers for the location. required: true + type: str publisher: description: - Name of an image publisher. List image offerings associated with a particular publisher. + type: str offer: description: - Name of an image offering. Combine with SKU to see a list of available image versions. + type: str sku: description: - Image offering SKU. Combine with offer to see a list of available versions. + type: str version: description: - Specific version number of an image. + type: str extends_documentation_fragment: - azure.azcollection.azure @@ -49,30 +54,29 @@ author: ''' EXAMPLES = ''' - - name: Get facts for a specific image - azure_rm_virtualmachineimage_info: - location: eastus - publisher: OpenLogic - offer: CentOS - sku: '7.1' - version: '7.1.20160308' - - - name: List available versions - azure_rm_virtualmachineimage_info: - location: eastus - publisher: OpenLogic - offer: CentOS - sku: '7.1' - - - name: List available offers - azure_rm_virtualmachineimage_info: - location: eastus - publisher: OpenLogic - - - name: List available publishers - azure_rm_virtualmachineimage_info: - location: eastus - +- name: Get facts for a specific image + azure_rm_virtualmachineimage_info: + location: eastus + publisher: OpenLogic + offer: CentOS + sku: '7.1' + version: '7.1.20160308' + +- name: List available versions + azure_rm_virtualmachineimage_info: + location: eastus + publisher: OpenLogic + offer: CentOS + sku: '7.1' + +- name: List available offers + azure_rm_virtualmachineimage_info: + location: eastus + publisher: OpenLogic + +- name: List available publishers + azure_rm_virtualmachineimage_info: + location: eastus ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescaleset.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescaleset.py index ee3b822b5..4a64628fb 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescaleset.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescaleset.py @@ -25,10 +25,12 @@ options: description: - Name of the resource group containing the virtual machine scale set. required: true + type: str name: description: - Name of the virtual machine. required: true + type: str state: description: - Assert the state of the virtual machine scale set. @@ -36,26 +38,32 @@ options: of the existing machine does not match, the machine will be updated. - State C(absent) will remove the virtual machine scale set. default: present + type: str choices: - absent - present location: description: - Valid Azure location. Defaults to location of the resource group. + type: str short_hostname: description: - Short host name. + type: str vm_size: description: - A valid Azure VM size value. For example, C(Standard_D4). - The list of choices varies depending on the subscription and location. Check your subscription for available choices. + type: str capacity: description: - Capacity of VMSS. default: 1 + type: int tier: description: - SKU Tier. + type: str choices: - Basic - Standard @@ -63,6 +71,7 @@ options: description: - Upgrade policy. - Required when creating the Azure virtual machine scale sets. + type: str choices: - Manual - Automatic @@ -70,6 +79,7 @@ options: description: - Priority of the VMSS. - C(None) is the equivalent of Regular VM. + type: str choices: - None - Spot @@ -77,6 +87,7 @@ options: description: - Specifies the eviction policy for the Azure Spot virtual machine. - Requires priority to be set to Spot. + type: str choices: - Deallocate - Delete @@ -87,13 +98,16 @@ options: - C(-1) indicates default price to be up-to on-demand. - Requires priority to be set to Spot. default: -1 + type: float admin_username: description: - Admin username used to access the host after it is created. Required when creating a VM. + type: str admin_password: description: - Password for the admin username. - Not required if the os_type is Linux and SSH password authentication is disabled by setting I(ssh_password_enabled=false). + type: str ssh_password_enabled: description: - When the os_type is Linux, setting I(ssh_password_enabled=false) will disable SSH password authentication and require use of SSH keys. @@ -106,6 +120,8 @@ options: - Set the C(path) to the default location of the authorized_keys files. - On an Enterprise Linux host, for example, the I(path=/home/<admin username>/.ssh/authorized_keys). Set C(key_data) to the actual value of the public key. + type: list + elements: dict image: description: - Specifies the image used to build the VM. @@ -115,10 +131,12 @@ options: - If a dict with the keys I(name) and I(resource_group), the image is sourced from a custom image based on the I(name) and I(resource_group) set. Note that the key I(resource_group) is optional and if omitted, all images in the subscription will be searched for by I(name). - Custom image support was added in Ansible 2.5. - required: true + - Required when creating. + type: raw os_disk_caching: description: - Type of OS disk caching. + type: str choices: - ReadOnly - ReadWrite @@ -133,6 +151,7 @@ options: os_type: description: - Base type of operating system. + type: str choices: - Windows - Linux @@ -145,6 +164,7 @@ options: managed_disk_type: description: - Managed disk type. + type: str choices: - Standard_LRS - Premium_LRS @@ -155,17 +175,22 @@ options: data_disks: description: - Describes list of data disks. + type: list + elements: dict suboptions: lun: description: - The logical unit number for data disk. - default: 0 + default: '0' + type: str disk_size_gb: description: - The initial disk size in GB for blank data disks. + type: int managed_disk_type: description: - Managed data disk type. + type: str choices: - Standard_LRS - Premium_LRS @@ -176,6 +201,7 @@ options: caching: description: - Type of data disk caching. + type: str choices: - ReadOnly - ReadWrite @@ -185,14 +211,17 @@ options: - When creating a virtual machine, if a specific virtual network from another resource group should be used. - Use this parameter to specify the resource group to use. + type: str virtual_network_name: description: - Virtual Network name. aliases: - virtual_network + type: str subnet_name: description: - Subnet name. + type: str aliases: - subnet public_ip_per_vm: @@ -203,14 +232,18 @@ options: load_balancer: description: - Load balancer name. + type: str application_gateway: description: - Application gateway name. + type: str remove_on_absent: description: - When removing a VM using I(state=absent), also remove associated resources. - It can be C(all) or a list with any of the following ['network_interfaces', 'virtual_storage', 'public_ips']. - Any other input will be ignored. + type: list + elements: str default: ['all'] enable_accelerated_networking: description: @@ -224,6 +257,7 @@ options: - It can be a dict which contains I(name) and I(resource_group) of the security group. aliases: - security_group_name + type: raw overprovision: description: - Specifies whether the Virtual Machine Scale Set should be overprovisioned. @@ -242,21 +276,26 @@ options: description: - Billing plan name. required: true + type: str product: description: - Product name. required: true + type: str publisher: description: - Publisher offering the plan. required: true + type: str promotion_code: description: - Optional promotion code. + type: str zones: description: - A list of Availability Zones for your virtual machine scale set. type: list + elements: str custom_data: description: - Data which is made available to the virtual machine and used by e.g., C(cloud-init). @@ -264,9 +303,11 @@ options: - If the image you are attempting to use is not listed in U(https://docs.microsoft.com/en-us/azure/virtual-machines/linux/using-cloud-init#cloud-init-overview), follow these steps U(https://docs.microsoft.com/en-us/azure/virtual-machines/linux/cloudinit-prepare-custom-image). + type: str scale_in_policy: description: - define the order in which vmss instances are scaled-in + type: str choices: - Default - NewestVM @@ -275,6 +316,7 @@ options: description: - timeout time for termination notification event - in range between 5 and 15 + type: int platform_fault_domain_count: description: - Fault Domain count for each placement group. @@ -411,7 +453,7 @@ EXAMPLES = ''' name: testvmss vm_size: Standard_DS1_v2 capacity: 120 - single_placement_group: False + single_placement_group: false virtual_network_name: testvnet upgrade_policy: Manual subnet_name: testsubnet @@ -458,9 +500,9 @@ EXAMPLES = ''' name: testVMSS{{ rpfx }} vm_size: Standard_D4s_v3 admin_username: testuser - single_placement_group: False + single_placement_group: false platform_fault_domain_count: 1 - public_ip_per_vm: True + public_ip_per_vm: true ssh_password_enabled: false ssh_public_keys: - path: /home/testuser/.ssh/authorized_keys @@ -472,9 +514,9 @@ EXAMPLES = ''' os_disk_caching: ReadWrite security_profile: uefi_settings: - secure_boot_enabled: True - v_tpm_enabled: False - encryption_at_host: False + secure_boot_enabled: true + v_tpm_enabled: false + encryption_at_host: false security_type: TrustedLaunch image: offer: 0001-com-ubuntu-server-jammy @@ -606,9 +648,8 @@ azure_vmss: import base64 try: - from msrestazure.azure_exceptions import CloudError from azure.core.exceptions import ResourceNotFoundError - from msrestazure.tools import parse_resource_id + from azure.mgmt.core.tools import parse_resource_id from azure.core.exceptions import ResourceNotFoundError except ImportError: @@ -644,25 +685,37 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase): admin_username=dict(type='str'), admin_password=dict(type='str', no_log=True), ssh_password_enabled=dict(type='bool', default=True), - ssh_public_keys=dict(type='list'), + ssh_public_keys=dict(type='list', elements='dict'), image=dict(type='raw'), os_disk_caching=dict(type='str', aliases=['disk_caching'], choices=['ReadOnly', 'ReadWrite'], default='ReadOnly'), os_type=dict(type='str', choices=['Linux', 'Windows'], default='Linux'), managed_disk_type=dict(type='str', choices=['Standard_LRS', 'Premium_LRS', 'StandardSSD_LRS', 'UltraSSD_LRS', 'Premium_ZRS', 'StandardSSD_ZRS']), - data_disks=dict(type='list'), + data_disks=dict( + type='list', + elements='dict', + options=dict( + lun=dict(type='str', default='0'), + disk_size_gb=dict(type='int'), + caching=dict(type='str', default='ReadOnly', choices=['ReadOnly', 'ReadWrite']), + managed_disk_type=dict( + type='str', + choices=['Standard_LRS', 'Premium_LRS', 'StandardSSD_LRS', 'UltraSSD_LRS', 'Premium_ZRS', 'StandardSSD_ZRS'] + ) + ) + ), subnet_name=dict(type='str', aliases=['subnet']), public_ip_per_vm=dict(type='bool', default=False), load_balancer=dict(type='str'), application_gateway=dict(type='str'), virtual_network_resource_group=dict(type='str'), virtual_network_name=dict(type='str', aliases=['virtual_network']), - remove_on_absent=dict(type='list', default=['all']), + remove_on_absent=dict(type='list', default=['all'], elements='str'), enable_accelerated_networking=dict(type='bool'), security_group=dict(type='raw', aliases=['security_group_name']), overprovision=dict(type='bool'), single_placement_group=dict(type='bool', default=False), - zones=dict(type='list'), + zones=dict(type='list', elements='str'), custom_data=dict(type='str'), plan=dict(type='dict', options=dict(publisher=dict(type='str', required=True), product=dict(type='str', required=True), name=dict(type='str', required=True), @@ -862,18 +915,18 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase): if self.state == 'present': differences = [] results = vmss_dict - current_osdisk = vmss_dict['properties']['virtualMachineProfile']['storageProfile']['osDisk'] - current_ephemeral = current_osdisk.get('diffDiskSettings', None) - current_properties = vmss_dict['properties']['virtualMachineProfile'] + current_osdisk = vmss_dict['virtual_machine_profile']['storage_profile']['os_disk'] + current_ephemeral = current_osdisk.get('diff_disk_settings', None) + current_properties = vmss_dict['virtual_machine_profile'] if self.priority and self.priority != current_properties.get('priority', 'None'): self.fail('VM Priority is not updatable: requested virtual machine priority is {0}'.format(self.priority)) if self.eviction_policy and \ - self.eviction_policy != current_properties.get('evictionPolicy', None): + self.eviction_policy != current_properties.get('eviction_policy', None): self.fail('VM Eviction Policy is not updatable: requested virtual machine eviction policy is {0}'.format(self.eviction_policy)) if self.max_price and \ - vmss_dict['properties']['virtualMachineProfile'].get('billingProfile', None) and \ - self.max_price != vmss_dict['properties']['virtualMachineProfile']['billingProfile'].get('maxPrice', None): + vmss_dict['virtual_machine_profile'].get('billing_profile', None) and \ + self.max_price != vmss_dict['virtual_machine_profile']['billing_profile'].get('max_price', None): self.fail('VM Maximum Price is not updatable: requested virtual machine maximum price is {0}'.format(self.max_price)) if self.ephemeral_os_disk and current_ephemeral is None: @@ -882,15 +935,15 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase): self.fail('Ephemeral OS disk not updatable: virtual machine scale set ephemeral OS disk is {0}'.format(self.ephemeral_os_disk)) if self.os_disk_size_gb and \ - self.os_disk_size_gb != vmss_dict['properties']['virtualMachineProfile']['storageProfile']['osDisk']['diskSizeGB']: + self.os_disk_size_gb != vmss_dict['virtual_machine_profile']['storage_profile']['os_disk']['disk_size_gb']: self.fail('VMSS OS disk size is not updatable: requested virtual machine OS disk size is {0}'.format(self.os_disk_size_gb)) if self.os_disk_caching and \ - self.os_disk_caching != vmss_dict['properties']['virtualMachineProfile']['storageProfile']['osDisk']['caching']: + self.os_disk_caching != vmss_dict['virtual_machine_profile']['storage_profile']['os_disk']['caching']: self.log('CHANGED: virtual machine scale set {0} - OS disk caching'.format(self.name)) differences.append('OS Disk caching') changed = True - vmss_dict['properties']['virtualMachineProfile']['storageProfile']['osDisk']['caching'] = self.os_disk_caching + vmss_dict['virtual_machine_profile']['storage_profile']['os_disk']['caching'] = self.os_disk_caching if self.capacity and \ self.capacity != vmss_dict['sku']['capacity']: @@ -900,35 +953,35 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase): vmss_dict['sku']['capacity'] = self.capacity if self.data_disks and \ - len(self.data_disks) != len(vmss_dict['properties']['virtualMachineProfile']['storageProfile'].get('dataDisks', [])): + len(self.data_disks) != len(vmss_dict['virtual_machine_profile']['storage_profile'].get('data_disks', [])): self.log('CHANGED: virtual machine scale set {0} - Data Disks'.format(self.name)) differences.append('Data Disks') changed = True if self.upgrade_policy and \ - self.upgrade_policy != vmss_dict['properties']['upgradePolicy']['mode']: + self.upgrade_policy != vmss_dict['upgrade_policy']['mode']: self.log('CHANGED: virtual machine scale set {0} - Upgrade Policy'.format(self.name)) differences.append('Upgrade Policy') changed = True - vmss_dict['properties']['upgradePolicy']['mode'] = self.upgrade_policy + vmss_dict['upgrade_policy']['mode'] = self.upgrade_policy if image_reference and \ - image_reference.as_dict() != vmss_dict['properties']['virtualMachineProfile']['storageProfile']['imageReference']: + image_reference.as_dict() != vmss_dict['virtual_machine_profile']['storage_profile']['image_reference']: self.log('CHANGED: virtual machine scale set {0} - Image'.format(self.name)) differences.append('Image') changed = True - vmss_dict['properties']['virtualMachineProfile']['storageProfile']['imageReference'] = image_reference.as_dict() + vmss_dict['virtual_machine_profile']['storage_profile']['image_reference'] = image_reference.as_dict() update_tags, vmss_dict['tags'] = self.update_tags(vmss_dict.get('tags', dict())) if update_tags: differences.append('Tags') changed = True - if self.overprovision is not None and bool(self.overprovision) != bool(vmss_dict['properties'].get('overprovision')): + if self.overprovision is not None and bool(self.overprovision) != bool(vmss_dict.get('overprovision')): differences.append('overprovision') changed = True - if bool(self.single_placement_group) != bool(vmss_dict['properties']['singlePlacementGroup']): + if bool(self.single_placement_group) != bool(vmss_dict['single_placement_group']): differences.append('single_placement_group') changed = True @@ -944,26 +997,26 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase): if timeout < 5 or timeout > 15: self.fail("terminate_event_timeout_minutes should >= 5 and <= 15") iso_8601_format = "PT" + str(timeout) + "M" - old = vmss_dict['properties']['virtualMachineProfile'].get('scheduledEventsProfile', {}).\ - get('terminateNotificationProfile', {}).get('notBeforeTimeout', "") + old = vmss_dict['virtual_machine_profile'].get('scheduled_events_profile', {}).\ + get('terminate_notification_profile', {}).get('not_before_timeout', "") if old != iso_8601_format: differences.append('terminateNotification') changed = True - vmss_dict['properties']['virtualMachineProfile'].setdefault('scheduledEventsProfile', {})['terminateNotificationProfile'] = { - 'notBeforeTimeout': iso_8601_format, + vmss_dict['virtual_machine_profile'].setdefault('scheduled_events_profile', {})['terminate_notification_profile'] = { + 'not_before_timeout': iso_8601_format, "enable": 'true' } - if self.scale_in_policy and self.scale_in_policy != vmss_dict['properties'].get('scaleInPolicy', {}).get('rules', [""])[0]: + if self.scale_in_policy and self.scale_in_policy != vmss_dict.get('scale_in_policy', {}).get('rules', [""])[0]: self.log("CHANGED: virtual machine sale sets {0} scale in policy".format(self.name)) differences.append('scaleInPolicy') changed = True - vmss_dict['properties'].setdefault('scaleInPolicy', {})['rules'] = [self.scale_in_policy] + vmss_dict.setdefault('scale_in_policy', {})['rules'] = [self.scale_in_policy] - nicConfigs = vmss_dict['properties']['virtualMachineProfile']['networkProfile']['networkInterfaceConfigurations'] + nicConfigs = vmss_dict['virtual_machine_profile']['network_profile']['network_interface_configurations'] - backend_address_pool = nicConfigs[0]['properties']['ipConfigurations'][0]['properties'].get('loadBalancerBackendAddressPools', []) - backend_address_pool += nicConfigs[0]['properties']['ipConfigurations'][0]['properties'].get('applicationGatewayBackendAddressPools', []) + backend_address_pool = nicConfigs[0]['ip_configurations'][0].get('load_balancer_backend_address_pools', []) + backend_address_pool += nicConfigs[0]['ip_configurations'][0].get('application_gateway_backend_address_pools', []) lb_or_ag_id = None if (len(nicConfigs) != 1 or len(backend_address_pool) != 1): support_lb_change = False # Currently not support for the vmss contains more than one loadbalancer @@ -980,51 +1033,51 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase): changed = True if self.custom_data: - if self.custom_data != vmss_dict['properties']['virtualMachineProfile']['osProfile'].get('customData'): + if self.custom_data != vmss_dict['virtual_machine_profile']['os_profile'].get('custom_data'): differences.append('custom_data') changed = True - vmss_dict['properties']['virtualMachineProfile']['osProfile']['customData'] = self.custom_data + vmss_dict['virtual_machine_profile']['os_profile']['custom_data'] = self.custom_data - if self.orchestration_mode and self.orchestration_mode != vmss_dict['properties'].get('orchestrationMode'): + if self.orchestration_mode and self.orchestration_mode != vmss_dict.get('orchestration_mode'): self.fail("The orchestration_mode parameter cannot be updated!") else: - self.orchestration_mode = vmss_dict['properties'].get('orchestrationMode') + self.orchestration_mode = vmss_dict.get('orchestration_mode') - if self.platform_fault_domain_count and self.platform_fault_domain_count != vmss_dict['properties'].get('platformFaultDomainCount'): + if self.platform_fault_domain_count and self.platform_fault_domain_count != vmss_dict.get('platform_fault_domain_count'): self.fail("The platform_fault_domain_count parameter cannot be updated!") if self.security_profile is not None: update_security_profile = False - if 'securityProfile' not in vmss_dict['properties']['virtualMachineProfile'].keys(): + if 'securityProfile' not in vmss_dict['virtual_machine_profile'].keys(): update_security_profile = True differences.append('security_profile') else: if self.security_profile.get('encryption_at_host') is not None: if bool(self.security_profile.get('encryption_at_host')) != \ - bool(vmss_dict['properties']['virtualMachineProfile']['securityProfile']['encryptionAtHost']): + bool(vmss_dict['virtual_machine_profile']['security_profile']['encryption_at_host']): update_security_profle = True else: self.security_profile['encryption_at_host'] = \ - vmss_dict['properties']['virtualMachineProfile']['securityProfile']['encryptionAtHost'] + vmss_dict['virtual_machine_profile']['security_profile']['encryption_at_host'] if self.security_profile.get('security_type') is not None: if self.security_profile.get('security_type') != \ - vmss_dict['properties']['virtualMachineProfile']['securityProfile']['securityType']: + vmss_dict['virtual_machine_profile']['security_profile']['security_type']: update_security_profile = True if self.security_profile.get('uefi_settings') is not None: if self.security_profile['uefi_settings'].get('secure_boot_enabled') is not None: if bool(self.security_profile['uefi_settings']['secure_boot_enabled']) != \ - bool(vmss_dict['properties']['virtualMachineProfile']['securityProfile']['uefiSettings']['secureBootEnabled']): + bool(vmss_dict['virtual_machine_profile']['security_profile']['uefi_settings']['secure_boot_nabled']): update_security_profile = True else: self.security_profile['uefi_settings']['secure_boot_enabled'] = \ - vmss_dict['properties']['virtualMachineProfile']['securityProfile']['uefiSettings']['secureBootEnabled'] + vmss_dict['virtual_machine_profile']['security_profile']['uefi_settings']['secure_boot_enabled'] if self.security_profile['uefi_settings'].get('v_tpm_enabled') is not None: if bool(self.security_profile['uefi_settings']['v_tpm_enabled']) != \ - bool(vmss_dict['properties']['virtualMachineProfile']['securityProfile']['uefiSettings']['vTpmEnabled']): + bool(vmss_dict['virtual_machine_profile']['security_profile']['uefi_settings']['v_tpm_enabled']): update_security_profile = True else: self.security_profile['uefi_settings']['v_tpm_enabled'] = \ - vmss_dict['properties']['virtualMachineProfile']['securityProfile']['uefiSettings']['vTpmEnabled'] + vmss_dict['virtual_machine_profile']['security_profile']['uefi_settings']['v_tpm_enabled'] if update_security_profile: changed = True differences.append('security_profile') @@ -1338,7 +1391,7 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase): self.log("Fetching subnet {0} in virtual network {1}".format(subnet_name, vnet_name)) try: subnet = self.network_client.subnets.get(self.virtual_network_resource_group, vnet_name, subnet_name) - except CloudError as exc: + except Exception as exc: self.fail("Error: fetching subnet {0} in virtual network {1} - {2}".format( subnet_name, vnet_name, diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescaleset_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescaleset_info.py index a2154d017..642f6b58d 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescaleset_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescaleset_info.py @@ -23,9 +23,11 @@ options: name: description: - Limit results to a specific virtual machine scale set. + type: str resource_group: description: - The resource group to search for the desired virtual machine scale set. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -39,6 +41,7 @@ options: - In Ansible 2.5 and lower facts are always returned in raw format. - Please note that this option will be deprecated in 2.10 when curated format will become the only supported format. default: 'raw' + type: str choices: - 'curated' - 'raw' @@ -51,21 +54,21 @@ author: ''' EXAMPLES = ''' - - name: Get facts for a virtual machine scale set - azure_rm_virtualmachinescaleset_info: - resource_group: myResourceGroup - name: testvmss001 - format: curated - - - name: Get facts for all virtual networks - azure_rm_virtualmachinescaleset_info: - resource_group: myResourceGroup - - - name: Get facts by tags - azure_rm_virtualmachinescaleset_info: - resource_group: myResourceGroup - tags: - - testing +- name: Get facts for a virtual machine scale set + azure_rm_virtualmachinescaleset_info: + resource_group: myResourceGroup + name: testvmss001 + format: curated + +- name: Get facts for all virtual networks + azure_rm_virtualmachinescaleset_info: + resource_group: myResourceGroup + +- name: Get facts by tags + azure_rm_virtualmachinescaleset_info: + resource_group: myResourceGroup + tags: + - testing ''' RETURN = ''' @@ -329,34 +332,34 @@ class AzureRMVirtualMachineScaleSetInfo(AzureRMModuleBase): ssh_password_enabled = False try: - subnet_id = (vmss['properties']['virtualMachineProfile']['networkProfile']['networkInterfaceConfigurations'][0] - ['properties']['ipConfigurations'][0]['properties']['subnet']['id']) + subnet_id = (vmss['virtual_machine_profile']['network_profile']['network_interface_configurations'][0] + ['ipConfigurations'][0]['subnet']['id']) subnet_name = re.sub('.*subnets\\/', '', subnet_id) except Exception: self.log('Could not extract subnet name') try: - backend_address_pool_id = (vmss['properties']['virtualMachineProfile']['networkProfile']['networkInterfaceConfigurations'][0] - ['properties']['ipConfigurations'][0]['properties']['loadBalancerBackendAddressPools'][0]['id']) + backend_address_pool_id = (vmss['virtual_machine_profile']['network_profile']['network_interface_configurations'][0] + ['ip_configurations'][0]['load_balancer_backend_address_pools'][0]['id']) load_balancer_name = re.sub('\\/backendAddressPools.*', '', re.sub('.*loadBalancers\\/', '', backend_address_pool_id)) virtual_network_name = re.sub('.*virtualNetworks\\/', '', re.sub('\\/subnets.*', '', subnet_id)) except Exception: self.log('Could not extract load balancer / virtual network name') try: - ssh_password_enabled = (not vmss['properties']['virtualMachineProfile']['osProfile'] - ['linuxConfiguration']['disablePasswordAuthentication']) + ssh_password_enabled = (not vmss['virtual_machine_profile']['os_profile'] + ['linux_configuration']['disable_password_authentication']) except Exception: self.log('Could not extract SSH password enabled') - data_disks = vmss['properties']['virtualMachineProfile']['storageProfile'].get('dataDisks', []) + data_disks = vmss['virtual_machine_profile']['storage_profile'].get('data_disks', []) for disk_index in range(len(data_disks)): old_disk = data_disks[disk_index] new_disk = { 'lun': old_disk['lun'], - 'disk_size_gb': old_disk['diskSizeGB'], - 'managed_disk_type': old_disk['managedDisk']['storageAccountType'], + 'disk_size_gb': old_disk['disk_size_gb'], + 'managed_disk_type': old_disk['managed_disk']['storage_account_type'], 'caching': old_disk['caching'] } data_disks[disk_index] = new_disk @@ -370,17 +373,17 @@ class AzureRMVirtualMachineScaleSetInfo(AzureRMModuleBase): 'vm_size': vmss['sku']['name'], 'capacity': vmss['sku']['capacity'], 'tier': vmss['sku']['tier'], - 'upgrade_policy': vmss['properties'].get('upgradePolicy'), - 'orchestrationMode': vmss['properties'].get('orchestrationMode'), - 'platformFaultDomainCount': vmss['properties'].get('platformFaultDomainCount'), - 'admin_username': vmss['properties']['virtualMachineProfile']['osProfile']['adminUsername'], - 'admin_password': vmss['properties']['virtualMachineProfile']['osProfile'].get('adminPassword'), + 'upgrade_policy': vmss.get('upgrade_policy'), + 'orchestrationMode': vmss.get('orchestration_mode'), + 'platformFaultDomainCount': vmss.get('platform_fault_domain_count'), + 'admin_username': vmss['virtual_machine_profile']['os_profile']['admin_username'], + 'admin_password': vmss['virtual_machine_profile']['os_profile'].get('admin_password'), 'ssh_password_enabled': ssh_password_enabled, - 'image': vmss['properties']['virtualMachineProfile']['storageProfile']['imageReference'], - 'os_disk_caching': vmss['properties']['virtualMachineProfile']['storageProfile']['osDisk']['caching'], - 'os_type': 'Linux' if (vmss['properties']['virtualMachineProfile']['osProfile'].get('linuxConfiguration') is not None) else 'Windows', - 'overprovision': vmss['properties'].get('overprovision'), - 'managed_disk_type': vmss['properties']['virtualMachineProfile']['storageProfile']['osDisk']['managedDisk']['storageAccountType'], + 'image': vmss['virtual_machine_profile']['storage_profile']['image_reference'], + 'os_disk_caching': vmss['virtual_machine_profile']['storage_profile']['os_disk']['caching'], + 'os_type': 'Linux' if (vmss['virtual_machine_profile']['os_profile'].get('linux_configuration') is not None) else 'Windows', + 'overprovision': vmss.get('overprovision'), + 'managed_disk_type': vmss['virtual_machine_profile']['storage_profile']['os_disk']['managed_disk']['storage_account_type'], 'data_disks': data_disks, 'virtual_network_name': virtual_network_name, 'subnet_name': subnet_name, diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetextension.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetextension.py index eec58bcf1..7385ca7d6 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetextension.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetextension.py @@ -24,35 +24,45 @@ options: description: - Name of a resource group where the VMSS extension exists or will be created. required: true + type: str vmss_name: description: - The name of the virtual machine where the extension should be create or updated. required: true + type: str name: description: - Name of the VMSS extension. + type: str + required: true location: description: - Valid Azure location. Defaults to location of the resource group. + type: str publisher: description: - The name of the extension handler publisher. + type: str type: description: - The type of the extension handler. + type: str type_handler_version: description: - The type version of the extension handler. + type: str settings: description: - A dictionary containing extension settings. - Settings depend on extension type. - Refer to U(https://docs.microsoft.com/en-us/azure/virtual-machines/extensions/overview) for more information. + type: dict protected_settings: description: - A dictionary containing protected extension settings. - Settings depend on extension type. - Refer to U(https://docs.microsoft.com/en-us/azure/virtual-machines/extensions/overview) for more information. + type: dict auto_upgrade_minor_version: description: - Whether the extension handler should be automatically upgraded across minor versions. @@ -62,6 +72,7 @@ options: - Assert the state of the extension. - Use C(present) to create or update an extension and C(absent) to delete it. default: present + type: str choices: - absent - present @@ -75,25 +86,25 @@ author: ''' EXAMPLES = ''' - - name: Install VMSS Extension - azure_rm_virtualmachinescalesetextension: - name: myvmssextension - location: eastus - resource_group: myResourceGroup - vmss_name: myvm - publisher: Microsoft.Azure.Extensions - type: CustomScript - type_handler_version: 2.0 - settings: '{"commandToExecute": "hostname"}' - auto_upgrade_minor_version: true - - - name: Remove VMSS Extension - azure_rm_virtualmachinescalesetextension: - name: myvmssextension - location: eastus - resource_group: myResourceGroup - vmss_name: myvm - state: absent +- name: Install VMSS Extension + azure_rm_virtualmachinescalesetextension: + name: myvmssextension + location: eastus + resource_group: myResourceGroup + vmss_name: myvm + publisher: Microsoft.Azure.Extensions + type: CustomScript + type_handler_version: 2.0 + settings: '{"commandToExecute": "hostname"}' + auto_upgrade_minor_version: true + +- name: Remove VMSS Extension + azure_rm_virtualmachinescalesetextension: + name: myvmssextension + location: eastus + resource_group: myResourceGroup + vmss_name: myvm + state: absent ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetextension_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetextension_info.py index 3c54de11a..58eadf271 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetextension_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetextension_info.py @@ -21,13 +21,16 @@ options: description: - The name of the resource group. required: True + type: str vmss_name: description: - The name of VMSS containing the extension. required: True + type: str name: description: - The name of the virtual machine extension. + type: str extends_documentation_fragment: - azure.azcollection.azure @@ -38,16 +41,16 @@ author: ''' EXAMPLES = ''' - - name: Get information on specific Virtual Machine Scale Set Extension - azure_rm_virtualmachineextension_info: - resource_group: myResourceGroup - vmss_name: myvmss - name: myextension - - - name: List installed Virtual Machine Scale Set Extensions - azure_rm_virtualmachineextension_info: - resource_group: myrg - vmss_name: myvmss +- name: Get information on specific Virtual Machine Scale Set Extension + azure_rm_virtualmachineextension_info: + resource_group: myResourceGroup + vmss_name: myvmss + name: myextension + +- name: List installed Virtual Machine Scale Set Extensions + azure_rm_virtualmachineextension_info: + resource_group: myrg + vmss_name: myvmss ''' RETURN = ''' @@ -117,7 +120,6 @@ extensions: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: - from msrest.serialization import Model from azure.core.exceptions import ResourceNotFoundError except ImportError: # This is handled in azure_rm_common diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetinstance.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetinstance.py index 54ed23b86..ca20000a8 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetinstance.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetinstance.py @@ -21,14 +21,17 @@ options: description: - The name of the resource group. required: True + type: str vmss_name: description: - The name of the VM scale set. required: True + type: str instance_id: description: - The instance ID of the virtual machine. - required: True + type: str + required: true latest_model: type: bool description: @@ -36,6 +39,7 @@ options: power_state: description: - Use this option to change power state of the instance. + type: str choices: - 'running' - 'stopped' @@ -52,6 +56,7 @@ options: description: - State of the VMSS instance. Use C(present) to update an instance and C(absent) to delete an instance. default: present + type: str choices: - absent - present @@ -65,19 +70,19 @@ author: ''' EXAMPLES = ''' - - name: Upgrade instance to the latest image - azure_rm_virtualmachinescalesetinstance: - resource_group: myResourceGroup - vmss_name: myVMSS - instance_id: "2" - latest_model: yes - - - name: Turn on protect from scale in - azure_rm_virtualmachinescalesetinstance: - resource_group: myResourceGroup - vmss_name: myVMSS - instance_id: "2" - protect_from_scale_in: true +- name: Upgrade instance to the latest image + azure_rm_virtualmachinescalesetinstance: + resource_group: myResourceGroup + vmss_name: myVMSS + instance_id: "2" + latest_model: true + +- name: Turn on protect from scale in + azure_rm_virtualmachinescalesetinstance: + resource_group: myResourceGroup + vmss_name: myVMSS + instance_id: "2" + protect_from_scale_in: true ''' RETURN = ''' @@ -100,7 +105,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError from azure.mgmt.compute import ComputeManagementClient - from msrest.serialization import Model except ImportError: # This is handled in azure_rm_common pass @@ -119,7 +123,8 @@ class AzureRMVirtualMachineScaleSetInstance(AzureRMModuleBase): required=True ), instance_id=dict( - type='str' + type='str', + required=True ), latest_model=dict( type='bool' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetinstance_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetinstance_info.py index 6d9888728..07b6cf92c 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetinstance_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetinstance_info.py @@ -21,13 +21,16 @@ options: description: - The name of the resource group. required: True + type: str vmss_name: description: - The name of the VM scale set. required: True + type: str instance_id: description: - The instance ID of the virtual machine. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -43,10 +46,10 @@ author: ''' EXAMPLES = ''' - - name: List VM instances in Virtual Machine ScaleSet - azure_rm_virtualmachinescalesetinstance_info: - resource_group: myResourceGroup - vmss_name: myVMSS +- name: List VM instances in Virtual Machine ScaleSet + azure_rm_virtualmachinescalesetinstance_info: + resource_group: myResourceGroup + vmss_name: myVMSS ''' RETURN = ''' @@ -118,7 +121,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.mgmt.compute import ComputeManagementClient - from msrest.serialization import Model from azure.core.exceptions import ResourceNotFoundError except ImportError: # This is handled in azure_rm_common diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinesize_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinesize_info.py index a0fe189af..982a7ea95 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinesize_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinesize_info.py @@ -40,14 +40,14 @@ author: ''' EXAMPLES = ''' - - name: Get all virtual machine size info in eastus - azure_rm_virtualmachinesize_info: - location: eastus - - - name: Get virtual machine size info for eastus for Standard_A1_v2 - azure_rm_virtualmachinesize_info: - location: eastus - name: Standard_A1_v2 +- name: Get all virtual machine size info in eastus + azure_rm_virtualmachinesize_info: + location: eastus + +- name: Get virtual machine size info for eastus for Standard_A1_v2 + azure_rm_virtualmachinesize_info: + location: eastus + name: Standard_A1_v2 ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetwork.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetwork.py index 2cbf0de55..c497fa3c3 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetwork.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetwork.py @@ -12,7 +12,7 @@ __metaclass__ = type DOCUMENTATION = ''' --- module: azure_rm_virtualnetwork -version_added: "0.1.0" +version_added: 0.1.0 short_description: Manage Azure virtual networks description: - Create, update or delete a virtual networks. Allows setting and updating the available IPv4 address ranges @@ -22,37 +22,44 @@ options: description: - Name of resource group. required: true + type: str address_prefixes_cidr: + aliases: + - address_prefixes description: - List of IPv4 address ranges where each is formatted using CIDR notation. - Required when creating a new virtual network or using I(purge_address_prefixes). - aliases: - - address_prefixes + elements: str + type: list dns_servers: description: - Custom list of DNS servers. - The first server in the list will be treated as the Primary server. This is an explicit list. - Existing DNS servers will be replaced with the specified list. - Use the I(purge_dns_servers) option to remove all custom DNS servers and revert to default Azure servers. + elements: str + type: list location: description: - Valid Azure location. Defaults to location of the resource group. + type: str name: description: - Name of the virtual network. required: true + type: str purge_address_prefixes: description: - Use with I(state=present) to remove any existing I(address_prefixes). type: bool - default: 'no' + default: false aliases: - purge purge_dns_servers: description: - Use with I(state=present) to remove existing DNS servers, reverting to default Azure servers. Mutually exclusive with DNS servers. type: bool - default: 'no' + default: false flow_timeout_in_minutes: description: - The FlowTimeout value (in minutes) for the Virtual Network. @@ -61,6 +68,7 @@ options: description: - State of the virtual network. Use C(present) to create or update and C(absent) to delete. default: present + type: str choices: - absent - present @@ -76,25 +84,25 @@ author: ''' EXAMPLES = ''' - - name: Create a virtual network - azure_rm_virtualnetwork: - resource_group: myResourceGroup - name: myVirtualNetwork - address_prefixes_cidr: - - "10.1.0.0/16" - - "172.100.0.0/16" - dns_servers: - - "127.0.0.1" - - "127.0.0.2" - tags: - testing: testing - delete: on-exit - - - name: Delete a virtual network - azure_rm_virtualnetwork: - resource_group: myResourceGroup - name: myVirtualNetwork - state: absent +- name: Create a virtual network + azure_rm_virtualnetwork: + resource_group: myResourceGroup + name: myVirtualNetwork + address_prefixes_cidr: + - 10.1.0.0/16 + - 172.100.0.0/16 + dns_servers: + - 127.0.0.1 + - 127.0.0.2 + tags: + testing: testing + delete: on-exit + +- name: Delete a virtual network + azure_rm_virtualnetwork: + resource_group: myResourceGroup + name: myVirtualNetwork + state: absent ''' RETURN = ''' state: @@ -217,8 +225,8 @@ class AzureRMVirtualNetwork(AzureRMModuleBase): name=dict(type='str', required=True), state=dict(type='str', default='present', choices=['present', 'absent']), location=dict(type='str'), - address_prefixes_cidr=dict(type='list', aliases=['address_prefixes']), - dns_servers=dict(type='list',), + address_prefixes_cidr=dict(type='list', elements='str', aliases=['address_prefixes']), + dns_servers=dict(type='list', elements='str'), purge_address_prefixes=dict(type='bool', default=False, aliases=['purge']), purge_dns_servers=dict(type='bool', default=False), flow_timeout_in_minutes=dict(type='int'), diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetwork_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetwork_info.py index 43bfb5314..072f8db7b 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetwork_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetwork_info.py @@ -24,9 +24,11 @@ options: name: description: - Only show results for a specific virtual network. + type: str resource_group: description: - Limit results by resource group. Required when filtering by name. + type: str tags: description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. @@ -43,19 +45,19 @@ author: ''' EXAMPLES = ''' - - name: Get facts for one virtual network - azure_rm_virtualnetwork_info: - resource_group: myResourceGroup - name: secgroup001 - - - name: Get facts for all virtual networks - azure_rm_virtualnetwork_info: - resource_group: myResourceGroup - - - name: Get facts by tags - azure_rm_virtualnetwork_info: - tags: - - testing +- name: Get facts for one virtual network + azure_rm_virtualnetwork_info: + resource_group: myResourceGroup + name: secgroup001 + +- name: Get facts for all virtual networks + azure_rm_virtualnetwork_info: + resource_group: myResourceGroup + +- name: Get facts by tags + azure_rm_virtualnetwork_info: + tags: + - testing ''' RETURN = ''' azure_virtualnetworks: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetworkgateway.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetworkgateway.py index 4371fb162..c5f8271cd 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetworkgateway.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetworkgateway.py @@ -22,14 +22,17 @@ options: description: - Name of a resource group where VPN Gateway exists or will be created. required: true + type: str name: description: - Name of VPN Gateway. required: true + type: str state: description: - State of the VPN Gateway. Use C(present) to create or update VPN gateway and C(absent) to delete VPN gateway. default: present + type: str choices: - absent - present @@ -37,7 +40,7 @@ options: location: description: - Valid Azure location. Defaults to location of the resource group. - required: false + type: str virtual_network: description: - An existing virtual network with which the VPN Gateway will be associated. @@ -46,35 +49,42 @@ options: - Must be in the same resource group as VPN gateway when specified by name. - Can be the resource ID of the virtual network. - Can be a dict which contains I(name) and I(resource_group) of the virtual network. + - Required when creating. + type: raw aliases: - virtual_network_name - required: true ip_configurations: description: - List of IP configurations. + type: list + elements: dict suboptions: name: description: - Name of the IP configuration. + type: str required: true private_ip_allocation_method: description: - Private IP allocation method. + type: str choices: - - dynamic - - static - default: dynamic + - Dynamic + - Static + default: Dynamic public_ip_address_name: description: - Name of the public IP address. Use 'None' to disable the public IP address. + type: str subnet: description: - ID of the gateway subnet for VPN. - default: GatewaySubnet + type: str gateway_type: description: - The type of this virtual network gateway. default: vpn + type: str choices: - vpn - express_route @@ -82,6 +92,7 @@ options: description: - The type of this virtual private network. default: route_based + type: str choices: - route_based - policy_based @@ -89,10 +100,12 @@ options: description: - Whether BGP is enabled for this virtual network gateway or not. default: false + type: bool sku: description: - The reference of the VirtualNetworkGatewaySku resource which represents the SKU selected for Virtual network gateway. default: VpnGw1 + type: str choices: - VpnGw1 - VpnGw2 @@ -104,6 +117,7 @@ options: description: - The generation for this VirtualNetworkGateway. Must be C(None) if C(gateway_type) is not VPN. default: Generation1 + type: str choices: - None - Generation1 @@ -111,10 +125,12 @@ options: bgp_settings: description: - Virtual network gateway's BGP speaker settings. + type: dict suboptions: asn: description: - The BGP speaker's ASN. + type: int required: True extends_documentation_fragment: @@ -126,54 +142,54 @@ author: ''' EXAMPLES = ''' - - name: Create virtual network gateway without bgp settings - azure_rm_virtualnetworkgateway: - resource_group: myResourceGroup - name: myVirtualNetworkGateway - ip_configurations: - - name: testipconfig - private_ip_allocation_method: Dynamic - public_ip_address_name: testipaddr - virtual_network: myVirtualNetwork - tags: - common: "xyz" - - - name: Create virtual network gateway Generation2 - azure_rm_virtualnetworkgateway: - resource_group: myResourceGroup - name: myVirtualNetworkGateway - sku: vpn_gw2 - vpn_gateway_generation: Generation2 - ip_configurations: - - name: testipconfig - private_ip_allocation_method: Dynamic - public_ip_address_name: testipaddr - virtual_network: myVirtualNetwork - tags: - common: "xyz" - - - name: Create virtual network gateway with bgp - azure_rm_virtualnetworkgateway: - resource_group: myResourceGroup - name: myVirtualNetworkGateway - sku: vpn_gw1 - ip_configurations: - - name: testipconfig - private_ip_allocation_method: Dynamic - public_ip_address_name: testipaddr - enable_bgp: yes - virtual_network: myVirtualNetwork - bgp_settings: - asn: 65515 - bgp_peering_address: "169.254.54.209" - tags: - common: "xyz" - - - name: Delete instance of virtual network gateway - azure_rm_virtualnetworkgateway: - resource_group: myResourceGroup - name: myVirtualNetworkGateway - state: absent +- name: Create virtual network gateway without bgp settings + azure_rm_virtualnetworkgateway: + resource_group: myResourceGroup + name: myVirtualNetworkGateway + ip_configurations: + - name: testipconfig + private_ip_allocation_method: Dynamic + public_ip_address_name: testipaddr + virtual_network: myVirtualNetwork + tags: + common: "xyz" + +- name: Create virtual network gateway Generation2 + azure_rm_virtualnetworkgateway: + resource_group: myResourceGroup + name: myVirtualNetworkGateway + sku: vpn_gw2 + vpn_gateway_generation: Generation2 + ip_configurations: + - name: testipconfig + private_ip_allocation_method: Dynamic + public_ip_address_name: testipaddr + virtual_network: myVirtualNetwork + tags: + common: "xyz" + +- name: Create virtual network gateway with bgp + azure_rm_virtualnetworkgateway: + resource_group: myResourceGroup + name: myVirtualNetworkGateway + sku: vpn_gw1 + ip_configurations: + - name: testipconfig + private_ip_allocation_method: Dynamic + public_ip_address_name: testipaddr + enable_bgp: true + virtual_network: myVirtualNetwork + bgp_settings: + asn: 65515 + bgp_peering_address: "169.254.54.209" + tags: + common: "xyz" + +- name: Delete instance of virtual network gateway + azure_rm_virtualnetworkgateway: + resource_group: myResourceGroup + name: myVirtualNetworkGateway + state: absent ''' RETURN = ''' @@ -192,7 +208,7 @@ except ImportError: # This is handled in azure_rm_common pass -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase, CIDR_PATTERN +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase from ansible.module_utils.common.dict_transformations import _snake_to_camel @@ -257,7 +273,7 @@ class AzureRMVirtualNetworkGateway(AzureRMModuleBase): vpn_type=dict(type='str', default='route_based', choices=['route_based', 'policy_based']), vpn_gateway_generation=dict(type='str', default='Generation1', choices=['None', 'Generation1', 'Generation2']), enable_bgp=dict(type='bool', default=False), - sku=dict(default='VpnGw1', choices=['VpnGw1', 'VpnGw2', 'VpnGw3', 'Standard', 'Basic', 'HighPerformance']), + sku=dict(type='str', default='VpnGw1', choices=['VpnGw1', 'VpnGw2', 'VpnGw3', 'Standard', 'Basic', 'HighPerformance']), bgp_settings=dict(type='dict', options=bgp_spec), virtual_network=dict(type='raw', aliases=['virtual_network_name']) ) @@ -274,12 +290,14 @@ class AzureRMVirtualNetworkGateway(AzureRMModuleBase): self.vpn_gateway_generation = None self.bgp_settings = None + required_if = [('state', 'present', ['virtual_network'])] self.results = dict( changed=False, state=dict() ) super(AzureRMVirtualNetworkGateway, self).__init__(derived_arg_spec=self.module_arg_spec, + required_if=required_if, supports_check_mode=True) def exec_module(self, **kwargs): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetworkpeering.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetworkpeering.py index 5bdc35f45..71025e25e 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetworkpeering.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetworkpeering.py @@ -20,13 +20,16 @@ options: description: - Name of a resource group where the vnet exists. required: true + type: str name: description: - Name of the virtual network peering. required: true + type: str virtual_network: description: - Name or resource ID of the virtual network to be peered. + type: raw required: true remote_virtual_network: description: @@ -35,6 +38,7 @@ options: - It can be remote virtual network resource ID. - It can be a dict which contains I(name) and I(resource_group) of remote virtual network. - Required when creating. + type: raw allow_virtual_network_access: description: - Allows VMs in the remote VNet to access all VMs in the local VNet. @@ -60,6 +64,7 @@ options: description: - State of the virtual network peering. Use C(present) to create or update a peering and C(absent) to delete it. default: present + type: str choices: - absent - present @@ -72,23 +77,23 @@ author: ''' EXAMPLES = ''' - - name: Create virtual network peering - azure_rm_virtualnetworkpeering: - resource_group: myResourceGroup - virtual_network: myVirtualNetwork - name: myPeering - remote_virtual_network: - resource_group: mySecondResourceGroup - name: myRemoteVirtualNetwork - allow_virtual_network_access: false - allow_forwarded_traffic: true - - - name: Delete the virtual network peering - azure_rm_virtualnetworkpeering: - resource_group: myResourceGroup - virtual_network: myVirtualNetwork - name: myPeering - state: absent +- name: Create virtual network peering + azure_rm_virtualnetworkpeering: + resource_group: myResourceGroup + virtual_network: myVirtualNetwork + name: myPeering + remote_virtual_network: + resource_group: mySecondResourceGroup + name: myRemoteVirtualNetwork + allow_virtual_network_access: false + allow_forwarded_traffic: true + +- name: Delete the virtual network peering + azure_rm_virtualnetworkpeering: + resource_group: myResourceGroup + virtual_network: myVirtualNetwork + name: myPeering + state: absent ''' RETURN = ''' id: @@ -107,7 +112,7 @@ peering_sync_level: ''' try: - from msrestazure.tools import is_valid_resource_id + from azure.mgmt.core.tools import is_valid_resource_id from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller except ImportError: @@ -177,7 +182,8 @@ class AzureRMVirtualNetworkPeering(AzureRMModuleBase): required=True ), virtual_network=dict( - type='raw' + type='raw', + required=True ), remote_virtual_network=dict( type='raw' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetworkpeering_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetworkpeering_info.py index 87563f01a..e48f4e49f 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetworkpeering_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualnetworkpeering_info.py @@ -20,13 +20,16 @@ options: description: - Name of a resource group where the vnet exists. required: True + type: str virtual_network: description: - Name or resource ID of a virtual network. required: True + type: raw name: description: - Name of the virtual network peering. + type: str extends_documentation_fragment: - azure.azcollection.azure @@ -36,16 +39,16 @@ author: ''' EXAMPLES = ''' - - name: Get virtual network peering by name - azure_rm_virtualnetworkpeering_info: - resource_group: myResourceGroup - virtual_network: myVnet1 - name: myVnetPeer +- name: Get virtual network peering by name + azure_rm_virtualnetworkpeering_info: + resource_group: myResourceGroup + virtual_network: myVnet1 + name: myVnetPeer - - name: List virtual network peering of virtual network - azure_rm_virtualnetworkpeering: - resource_group: myResourceGroup - virtual_network: myVnet1 +- name: List virtual network peering of virtual network + azure_rm_virtualnetworkpeering: + resource_group: myResourceGroup + virtual_network: myVnet1 ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualwan.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualwan.py index 10869012d..38c542695 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualwan.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualwan.py @@ -48,6 +48,7 @@ options: description: - List of VirtualHubs in the VirtualWAN. type: list + elements: dict suboptions: id: description: @@ -57,11 +58,12 @@ options: description: - List of VpnSites in the VirtualWAN. type: list + elements: dict suboptions: id: - description: - - The vpn site resource ID. - type: str + description: + - The vpn site resource ID. + type: str allow_branch_to_branch_traffic: description: - True if branch to branch traffic is allowed. @@ -82,6 +84,7 @@ options: - Assert the state of the VirtualWan. - Use C(present) to create or update an VirtualWan and C(absent) to delete it. default: present + type: str choices: - absent - present @@ -94,21 +97,20 @@ author: ''' EXAMPLES = ''' - - name: Create a VirtualWan - azure_rm_virtualwan: - resource_group: myResouceGroup - name: testwan - disable_vpn_encryption: true - allow_branch_to_branch_traffic: true - allow_vnet_to_vnet_traffic: true - virtual_wan_type: Standard - - - name: Delete the VirtualWan - azure_rm_virtualwan: - resource_group: myResouceGroup - name: testwan - state: absent - +- name: Create a VirtualWan + azure_rm_virtualwan: + resource_group: myResouceGroup + name: testwan + disable_vpn_encryption: true + allow_branch_to_branch_traffic: true + allow_vnet_to_vnet_traffic: true + virtual_wan_type: Standard + +- name: Delete the VirtualWan + azure_rm_virtualwan: + resource_group: myResouceGroup + name: testwan + state: absent ''' RETURN = ''' @@ -221,7 +223,6 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from msrestazure.azure_operation import AzureOperationPoller except ImportError: # This is handled in azure_rm_common pass @@ -255,6 +256,7 @@ class AzureRMVirtualWan(AzureRMModuleBaseExt): ), virtual_hubs=dict( type='list', + elements='dict', updatable=False, disposition='/virtual_hubs', options=dict( @@ -266,6 +268,7 @@ class AzureRMVirtualWan(AzureRMModuleBaseExt): ), vpn_sites=dict( type='list', + elements='dict', updatable=False, disposition='/vpn_sites', options=dict( @@ -365,7 +368,7 @@ class AzureRMVirtualWan(AzureRMModuleBaseExt): response = self.network_client.virtual_wans.begin_create_or_update(resource_group_name=self.resource_group, virtual_wan_name=self.name, wan_parameters=self.body) - if isinstance(response, AzureOperationPoller) or isinstance(response, LROPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: self.log('Error attempting to create the VirtualWan instance.') diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualwan_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualwan_info.py index 562422129..4c395a415 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualwan_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualwan_info.py @@ -32,18 +32,17 @@ author: ''' EXAMPLES = ''' - - name: Get Virtual WAN by name - azure_rm_virtualwan_info: - resource_group: myResouceGroup - name: testwan +- name: Get Virtual WAN by name + azure_rm_virtualwan_info: + resource_group: myResouceGroup + name: testwan - - name: List all Virtual WANLs by resource group - azure_rm_virtualwan_info: - resource_group: myResourceGroup - - - name: List all Virtual WANs by subscription_id - azure_rm_virtualwan_info: +- name: List all Virtual WANLs by resource group + azure_rm_virtualwan_info: + resource_group: myResourceGroup +- name: List all Virtual WANs by subscription_id + azure_rm_virtualwan_info: ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmbackuppolicy.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmbackuppolicy.py index 3f6a6e862..5cd10c978 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmbackuppolicy.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmbackuppolicy.py @@ -42,18 +42,21 @@ options: required: false default: ['Monday'] type: list + elements: str weeks: description: - List of weeks of month. required: false default: ['First'] type: list + elements: str months: description: - List of months of year of yearly retention policy. required: false default: ['January'] type: list + elements: str count: description: - Count of duration types. Retention duration is obtained by the counting the duration type Count times. @@ -235,14 +238,17 @@ class VMBackupPolicy(AzureRMModuleBaseExt): ), weekdays=dict( type='list', + elements='str', default=['Monday'] ), weeks=dict( type='list', + elements='str', default=['First'] ), months=dict( type='list', + elements='str', default=['January'] ), count=dict( @@ -360,6 +366,7 @@ class VMBackupPolicy(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) old_response = self.get_resource() @@ -397,9 +404,9 @@ class VMBackupPolicy(AzureRMModuleBaseExt): self.fail('Error in creating Backup Policy {0}'.format(str(e))) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: - response = {'text': response.text} + response = {'text': response.context['deserialized_data']} return response @@ -420,12 +427,6 @@ class VMBackupPolicy(AzureRMModuleBaseExt): self.log('Error attempting to delete Azure Backup policy.') self.fail('Error attempting to delete Azure Backup policy: {0}'.format(str(e))) - try: - response = json.loads(response.text) - except Exception: - response = {'text': response.text} - return response - def get_resource(self): # self.log('Fetch Backup Policy Details {0}'.format(self.)) found = False @@ -444,7 +445,7 @@ class VMBackupPolicy(AzureRMModuleBaseExt): except Exception as e: self.log('Backup policy does not exist.') if found is True: - response = json.loads(response.text) + response = json.loads(response.body()) return response else: return False diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmbackuppolicy_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmbackuppolicy_info.py index 18aaf718c..0aa7b5918 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmbackuppolicy_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmbackuppolicy_info.py @@ -38,10 +38,11 @@ author: ''' EXAMPLES = ''' - azure_rm_backvmuppolicy_info: - name: 'myBackupPolicy' - vault_name: 'myVault' - resource_group: 'myResourceGroup' +- name: Get backvm policy facts + azure_rm_backvmuppolicy_info: + name: 'myBackupPolicy' + vault_name: 'myVault' + resource_group: 'myResourceGroup' ''' RETURN = ''' @@ -215,6 +216,7 @@ class BackupPolicyVMInfo(AzureRMModuleBaseExt): self.url = self.get_url() self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) response = self.get_resource() @@ -242,9 +244,9 @@ class BackupPolicyVMInfo(AzureRMModuleBaseExt): self.log('Backup policy does not exist.') self.fail('Error in fetching VM Backup Policy {0}'.format(str(e))) try: - response = json.loads(response.text) + response = json.loads(response.body()) except Exception: - response = {'text': response.text} + response = {'text': response.context['deserialized_data']} return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmssnetworkinterface_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmssnetworkinterface_info.py index e7f2b8474..ac7c5be10 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmssnetworkinterface_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmssnetworkinterface_info.py @@ -49,23 +49,23 @@ author: ''' EXAMPLES = ''' - - name: Get information by the network name - azure_rm_vmssnetworkinterface_info: - resource_group: myResourceGroup - name: nic001 - vmss_name: testVMSS - vm_index: 0 - - - name: Get all network interface information in virtual machine scale set - azure_rm_vmssnetworkinterface_info: - resource_group: myResourceGroup - vmss_name: testVMSS - - - name: Get all network interface information in the same virtual machine index. - azure_rm_vmssnetworkinterface_info: - resource_group: myResourceGroup - vmss_name: testVMSS - vm_index: 1 +- name: Get information by the network name + azure_rm_vmssnetworkinterface_info: + resource_group: myResourceGroup + name: nic001 + vmss_name: testVMSS + vm_index: 0 + +- name: Get all network interface information in virtual machine scale set + azure_rm_vmssnetworkinterface_info: + resource_group: myResourceGroup + vmss_name: testVMSS + +- name: Get all network interface information in the same virtual machine index. + azure_rm_vmssnetworkinterface_info: + resource_group: myResourceGroup + vmss_name: testVMSS + vm_index: 1 ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vpnsite.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vpnsite.py index e72c5474e..32d4fafee 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vpnsite.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vpnsite.py @@ -205,16 +205,15 @@ author: ''' EXAMPLES = ''' - - name: Create VpnSite - azure_rm_vpnsite: - resource_group: myResourceGroup - name: vpnSite_name - - - name: Delete Vpn Site - azure_rm_vpnsite: - resource_group: myResourceGroup - name: vpnSite_name - +- name: Create VpnSite + azure_rm_vpnsite: + resource_group: myResourceGroup + name: vpnSite_name + +- name: Delete Vpn Site + azure_rm_vpnsite: + resource_group: myResourceGroup + name: vpnSite_name ''' RETURN = ''' @@ -300,7 +299,6 @@ state: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt try: - from msrestazure.azure_operation import AzureOperationPoller from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller except ImportError: @@ -572,7 +570,7 @@ class AzureRMVpnSite(AzureRMModuleBaseExt): response = self.network_client.vpn_sites.begin_create_or_update(resource_group_name=self.resource_group, vpn_site_name=self.name, vpn_site_parameters=self.body) - if isinstance(response, AzureOperationPoller) or isinstance(response, LROPoller): + if isinstance(response, LROPoller): response = self.get_poller_result(response) except Exception as exc: self.log('Error attempting to create the VpnSite instance.') diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vpnsite_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vpnsite_info.py index 0799959ab..36fb4b268 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vpnsite_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vpnsite_info.py @@ -33,18 +33,17 @@ author: ''' EXAMPLES = ''' - - name: Get Vpn Site Info by name - azure_rm_vpnsite_info: - resource_group: myResourceGroup - name: vwan_site_name +- name: Get Vpn Site Info by name + azure_rm_vpnsite_info: + resource_group: myResourceGroup + name: vwan_site_name - - name: Get Vpn Site List By ResourceGroup - azure_rm_vpnsite_info: - resource_group: myResourceGroup - - - name: Get Vpn Site List By Subscription - azure_rm_vpnsite_info: +- name: Get Vpn Site List By ResourceGroup + azure_rm_vpnsite_info: + resource_group: myResourceGroup +- name: Get Vpn Site List By Subscription + azure_rm_vpnsite_info: ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vpnsitelink_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vpnsitelink_info.py index 5643d785f..2759b0fec 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vpnsitelink_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vpnsitelink_info.py @@ -40,17 +40,17 @@ author: ''' EXAMPLES = ''' - - name: Get Vpn Site Link info by the name - azure_rm_vpnsitelink_info: - resource_group: myResourceGroup - name: vpnSiteLink1 - vpn_site_name: vpnSite1 +- name: Get Vpn Site Link info by the name + azure_rm_vpnsitelink_info: + resource_group: myResourceGroup + name: vpnSiteLink1 + vpn_site_name: vpnSite1 - - name: Get Vpn Site Links by the Vpn Site - azure_rm_vpnsitelink_info: - resource_group: myResourceGroup - vpn_site_name: vpnSite1 +- name: Get Vpn Site Links by the Vpn Site + azure_rm_vpnsitelink_info: + resource_group: myResourceGroup + vpn_site_name: vpnSite1 ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webapp.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webapp.py index 50256ea0c..05697176b 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webapp.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webapp.py @@ -21,14 +21,17 @@ options: description: - Name of the resource group to which the resource belongs. required: True + type: str name: description: - Unique name of the app to create or update. To create or update a deployment slot, use the {slot} parameter. required: True + type: str location: description: - Resource location. If not set, location from the resource group will be used as default. + type: str plan: description: @@ -42,11 +45,14 @@ options: - C(sku), SKU of app service plan, allowed values listed on U(https://azure.microsoft.com/en-us/pricing/details/app-service/linux/). - C(is_linux), whether or not the app service plan is Linux. defaults to C(False). - C(number_of_workers), number of workers for app service plan. + type: raw frameworks: description: - Set of run time framework settings. Each setting is a dictionary. - See U(https://docs.microsoft.com/en-us/azure/app-service/app-service-web-overview) for more info. + type: list + elements: dict suboptions: name: description: @@ -57,6 +63,8 @@ options: - Linux web apps support C(java), C(ruby), C(php), C(python), C(dotnetcore), and C(node) from June 2018. - Linux web apps support only one framework. - Java framework is mutually exclusive with others. + type: str + required: true choices: - java - net_framework @@ -75,42 +83,56 @@ options: - C(dotnetcore) supported value sample, C(1.0), C(1.1), C(1.2). - C(ruby) supported value sample, C(2.3). - C(java) supported value sample, C(1.9) for Windows web app. C(1.8) for Linux web app. + type: str + required: true settings: description: - List of settings of the framework. + type: dict suboptions: java_container: description: - Name of Java container. - Supported only when I(frameworks=java). Sample values C(Tomcat), C(Jetty). + type: str + required: True java_container_version: description: - Version of Java container. - Supported only when I(frameworks=java). - Sample values for C(Tomcat), C(8.0), C(8.5), C(9.0). For C(Jetty,), C(9.1), C(9.3). + type: str + required: True container_settings: description: - Web app container settings. + type: dict suboptions: name: description: - Name of the container, for example C(imagename:tag). - To create a multi-container app, the name should be 'COMPOSE|' or 'KUBE|' followed by base64 encoded configuration. + type: str + required: True registry_server_url: description: - Container registry server URL, for example C(mydockerregistry.io). + type: str registry_server_user: description: - The container registry server user name. + type: str registry_server_password: description: - The container registry server password. + type: str scm_type: description: - Repository type of deployment source, for example C(LocalGit), C(GitHub). - List of supported values maintained at U(https://docs.microsoft.com/en-us/rest/api/appservice/webapps/createorupdate#scmtype). + type: str always_on: description: @@ -138,18 +160,22 @@ options: deployment_source: description: - Deployment source for git. + type: dict suboptions: url: description: - Repository url of deployment source. + type: str branch: description: - The branch name of the repository. + type: str startup_file: description: - The web's startup file. - Used only for Linux web apps. + type: str client_affinity_enabled: description: @@ -165,6 +191,7 @@ options: app_settings: description: - Configure web app application settings. Suboptions are in key value pair format. + type: dict purge_app_settings: description: @@ -187,6 +214,7 @@ options: - State of the Web App. - Use C(present) to create or update a Web App and C(absent) to delete it. default: present + type: str choices: - absent - present @@ -201,121 +229,121 @@ author: ''' EXAMPLES = ''' - - name: Create a windows web app with non-exist app service plan - azure_rm_webapp: - resource_group: myResourceGroup - name: myWinWebapp - plan: - resource_group: myAppServicePlan_rg - name: myAppServicePlan - is_linux: false - sku: S1 - - - name: Create a docker web app with some app settings, with docker image - azure_rm_webapp: - resource_group: myResourceGroup - name: myDockerWebapp - plan: - resource_group: myAppServicePlan_rg - name: myAppServicePlan - is_linux: true - sku: S1 - number_of_workers: 2 - app_settings: - testkey: testvalue - testkey2: testvalue2 - container_settings: - name: ansible/ansible:ubuntu1404 - - - name: Create a docker web app with private acr registry - azure_rm_webapp: - resource_group: myResourceGroup - name: myDockerWebapp - plan: myAppServicePlan - app_settings: - testkey: testvalue - container_settings: - name: ansible/ubuntu1404 - registry_server_url: myregistry.io - registry_server_user: user - registry_server_password: pass - - - name: Create a multi-container web app - azure_rm_webapp: - resource_group: myResourceGroup - name: myMultiContainerWebapp - plan: myAppServicePlan - app_settings: - testkey: testvalue - container_settings: - name: "COMPOSE|{{ lookup('file', 'docker-compose.yml') | b64encode }}" - - - name: Create a linux web app with Node 6.6 framework - azure_rm_webapp: - resource_group: myResourceGroup - name: myLinuxWebapp - plan: - resource_group: myAppServicePlan_rg - name: myAppServicePlan - app_settings: - testkey: testvalue - frameworks: - - name: "node" - version: "6.6" - - - name: Create a windows web app with node, php - azure_rm_webapp: - resource_group: myResourceGroup - name: myWinWebapp - plan: - resource_group: myAppServicePlan_rg - name: myAppServicePlan - app_settings: - testkey: testvalue - frameworks: - - name: "node" - version: 6.6 - - name: "php" - version: "7.0" - - - name: Create a stage deployment slot for an existing web app - azure_rm_webapp: - resource_group: myResourceGroup - name: myWebapp/slots/stage - plan: - resource_group: myAppServicePlan_rg - name: myAppServicePlan - app_settings: - testkey:testvalue - - - name: Create a linux web app with java framework - azure_rm_webapp: - resource_group: myResourceGroup - name: myLinuxWebapp - plan: - resource_group: myAppServicePlan_rg - name: myAppServicePlan - app_settings: - testkey: testvalue - frameworks: - - name: "java" - version: "8" - settings: - java_container: "Tomcat" - java_container_version: "8.5" - - - name: Create a linux web app with python framework - azure_rm_webapp: - resource_group: myResourceGroup - name: myLinuxWebapp - plan: - resource_group: myAppServicePlan_rg - name: myAppServicePlan - app_settings: - testkey: testvalue - frameworks: - - name: "python" - version: "3.10" +- name: Create a windows web app with non-exist app service plan + azure_rm_webapp: + resource_group: myResourceGroup + name: myWinWebapp + plan: + resource_group: myAppServicePlan_rg + name: myAppServicePlan + is_linux: false + sku: S1 + +- name: Create a docker web app with some app settings, with docker image + azure_rm_webapp: + resource_group: myResourceGroup + name: myDockerWebapp + plan: + resource_group: myAppServicePlan_rg + name: myAppServicePlan + is_linux: true + sku: S1 + number_of_workers: 2 + app_settings: + testkey: testvalue + testkey2: testvalue2 + container_settings: + name: ansible/ansible:ubuntu1404 + +- name: Create a docker web app with private acr registry + azure_rm_webapp: + resource_group: myResourceGroup + name: myDockerWebapp + plan: myAppServicePlan + app_settings: + testkey: testvalue + container_settings: + name: ansible/ubuntu1404 + registry_server_url: myregistry.io + registry_server_user: user + registry_server_password: pass + +- name: Create a multi-container web app + azure_rm_webapp: + resource_group: myResourceGroup + name: myMultiContainerWebapp + plan: myAppServicePlan + app_settings: + testkey: testvalue + container_settings: + name: "COMPOSE|{{ lookup('file', 'docker-compose.yml') | b64encode }}" + +- name: Create a linux web app with Node 6.6 framework + azure_rm_webapp: + resource_group: myResourceGroup + name: myLinuxWebapp + plan: + resource_group: myAppServicePlan_rg + name: myAppServicePlan + app_settings: + testkey: testvalue + frameworks: + - name: "node" + version: "6.6" + +- name: Create a windows web app with node, php + azure_rm_webapp: + resource_group: myResourceGroup + name: myWinWebapp + plan: + resource_group: myAppServicePlan_rg + name: myAppServicePlan + app_settings: + testkey: testvalue + frameworks: + - name: "node" + version: 6.6 + - name: "php" + version: "7.0" + +- name: Create a stage deployment slot for an existing web app + azure_rm_webapp: + resource_group: myResourceGroup + name: myWebapp/slots/stage + plan: + resource_group: myAppServicePlan_rg + name: myAppServicePlan + app_settings: + testkey:testvalue + +- name: Create a linux web app with java framework + azure_rm_webapp: + resource_group: myResourceGroup + name: myLinuxWebapp + plan: + resource_group: myAppServicePlan_rg + name: myAppServicePlan + app_settings: + testkey: testvalue + frameworks: + - name: "java" + version: "8" + settings: + java_container: "Tomcat" + java_container_version: "8.5" + +- name: Create a linux web app with python framework + azure_rm_webapp: + resource_group: myResourceGroup + name: myLinuxWebapp + plan: + resource_group: myAppServicePlan_rg + name: myAppServicePlan + app_settings: + testkey: testvalue + frameworks: + - name: "python" + version: "3.10" ''' RETURN = ''' @@ -327,7 +355,6 @@ id: sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Web/sites/myWebApp" ''' -import time from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webapp_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webapp_info.py index 36b3eb3d3..af035b152 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webapp_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webapp_info.py @@ -23,9 +23,11 @@ options: name: description: - Only show results for a specific web app. + type: str resource_group: description: - Limit results by resource group. + type: str return_publish_profile: description: - Indicate whether to return publishing profile of the web app. @@ -45,20 +47,20 @@ author: ''' EXAMPLES = ''' - - name: Get facts for web app by name - azure_rm_webapp_info: - resource_group: myResourceGroup - name: winwebapp1 +- name: Get facts for web app by name + azure_rm_webapp_info: + resource_group: myResourceGroup + name: winwebapp1 - - name: Get facts for web apps in resource group - azure_rm_webapp_info: - resource_group: myResourceGroup +- name: Get facts for web apps in resource group + azure_rm_webapp_info: + resource_group: myResourceGroup - - name: Get facts for web apps with tags - azure_rm_webapp_info: - tags: - - testtag - - foo:bar +- name: Get facts for web apps with tags + azure_rm_webapp_info: + tags: + - testtag + - foo:bar ''' RETURN = ''' @@ -441,20 +443,20 @@ class AzureRMWebAppInfo(AzureRMModuleBase): curated_output = dict() curated_output['id'] = webapp['id'] curated_output['name'] = webapp['name'] - curated_output['resource_group'] = webapp['properties']['resourceGroup'] + curated_output['resource_group'] = webapp['resource_group'] curated_output['location'] = webapp['location'] - curated_output['plan'] = webapp['properties']['serverFarmId'] + curated_output['plan'] = webapp['server_farm_id'] curated_output['tags'] = webapp.get('tags', None) # important properties from output. not match input arguments. - curated_output['app_state'] = webapp['properties']['state'] - curated_output['availability_state'] = webapp['properties']['availabilityState'] - curated_output['default_host_name'] = webapp['properties']['defaultHostName'] - curated_output['host_names'] = webapp['properties']['hostNames'] - curated_output['enabled'] = webapp['properties']['enabled'] - curated_output['enabled_host_names'] = webapp['properties']['enabledHostNames'] - curated_output['host_name_ssl_states'] = webapp['properties']['hostNameSslStates'] - curated_output['outbound_ip_addresses'] = webapp['properties']['outboundIpAddresses'] + curated_output['app_state'] = webapp['state'] + curated_output['availability_state'] = webapp['availability_state'] + curated_output['default_host_name'] = webapp['default_host_name'] + curated_output['host_names'] = webapp['host_names'] + curated_output['enabled'] = webapp['enabled'] + curated_output['enabled_host_names'] = webapp['enabled_host_names'] + curated_output['host_name_ssl_states'] = webapp['host_name_ssl_states'] + curated_output['outbound_ip_addresses'] = webapp['outbound_ip_addresses'] # curated site_config if configuration: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappaccessrestriction.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappaccessrestriction.py index d8b49a335..bfe2b7591 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappaccessrestriction.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappaccessrestriction.py @@ -39,6 +39,7 @@ options: - The web app's HTTP access restrictions. type: list elements: dict + default: [] suboptions: name: description: @@ -73,6 +74,7 @@ options: the SCM restrictions will be configured but not used. type: list elements: dict + default: [] suboptions: name: description: @@ -116,26 +118,26 @@ author: ''' EXAMPLES = ''' - - name: Configure web app access restrictions. - azure.azcollection.azure_rm_webappaccessrestriction: - name: "MyWebapp" - resource_group: "MyResourceGroup" - ip_security_restrictions: - - name: "Datacenter 1" - action: "Allow" - ip_address: "1.1.1.1/24" - priority: 1 - - name: "Datacenter 2" - action: "Allow" - ip_address: "2.2.2.2/24" - priority: 2 - scm_ip_security_restrictions_use_main: true - - - name: Delete web app network access restrictions. - azure.azcollection.azure_rm_webappaccessrestriction: - name: "MyWebapp" - resource_group: "MyResourceGroup" - state: "absent" +- name: Configure web app access restrictions. + azure.azcollection.azure_rm_webappaccessrestriction: + name: "MyWebapp" + resource_group: "MyResourceGroup" + ip_security_restrictions: + - name: "Datacenter 1" + action: "Allow" + ip_address: "1.1.1.1/24" + priority: 1 + - name: "Datacenter 2" + action: "Allow" + ip_address: "2.2.2.2/24" + priority: 2 + scm_ip_security_restrictions_use_main: true + +- name: Delete web app network access restrictions. + azure.azcollection.azure_rm_webappaccessrestriction: + name: "MyWebapp" + resource_group: "MyResourceGroup" + state: "absent" ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappaccessrestriction_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappaccessrestriction_info.py index 0c3eb3260..2d07bc2de 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappaccessrestriction_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappaccessrestriction_info.py @@ -35,10 +35,10 @@ author: ''' EXAMPLES = ''' - - name: View web app access restrictions. - azure.azcollection.azure_rm_webappaccessrestriction_info: - name: "MyWebapp" - resource_group: "MyResourceGroup" +- name: View web app access restrictions. + azure.azcollection.azure_rm_webappaccessrestriction_info: + name: "MyWebapp" + resource_group: "MyResourceGroup" ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappslot.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappslot.py index 08ca490b0..85b7e96c8 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappslot.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappslot.py @@ -21,28 +21,35 @@ options: description: - Name of the resource group to which the resource belongs. required: True + type: str name: description: - Unique name of the deployment slot to create or update. required: True + type: str webapp_name: description: - Web app name which this deployment slot belongs to. required: True + type: str location: description: - Resource location. If not set, location from the resource group will be used as default. + type: str configuration_source: description: - Source slot to clone configurations from when creating slot. Use webapp's name to refer to the production slot. + type: str auto_swap_slot_name: description: - Used to configure target slot name to auto swap, or disable auto swap. - Set it target slot name to auto swap. - Set it to False to disable auto slot swap. + type: raw swap: description: - Swap deployment slots of a web app. + type: dict suboptions: action: description: @@ -50,6 +57,7 @@ options: - C(preview) is to apply target slot settings on source slot first. - C(swap) is to complete swapping. - C(reset) is to reset the swap. + type: str choices: - preview - swap @@ -58,6 +66,7 @@ options: target_slot: description: - Name of target slot to swap. If set to None, then swap with production slot. + type: str preserve_vnet: description: - C(True) to preserve virtual network to the slot during swap. Otherwise C(False). @@ -67,6 +76,8 @@ options: description: - Set of run time framework settings. Each setting is a dictionary. - See U(https://docs.microsoft.com/en-us/azure/app-service/app-service-web-overview) for more info. + type: list + elements: dict suboptions: name: description: @@ -77,6 +88,8 @@ options: - Linux web apps support C(java), C(ruby), C(php), C(dotnetcore), and C(node) from June 2018. - Linux web apps support only one framework. - Java framework is mutually exclusive with others. + type: str + required: true choices: - java - net_framework @@ -95,40 +108,55 @@ options: - C(dotnetcore) supported value sample, C(1.0), C(1.1), C(1.2). - C(ruby) supported value sample, 2.3. - C(java) supported value sample, C(1.9) for Windows web app. C(1.8) for Linux web app. + type: str + required: true settings: description: - List of settings of the framework. + type: dict suboptions: java_container: description: - Name of Java container. This is supported by specific framework C(java) onlys, for example C(Tomcat), C(Jetty). + type: str + required: true java_container_version: description: - Version of Java container. This is supported by specific framework C(java) only. - For C(Tomcat), for example C(8.0), C(8.5), C(9.0). For C(Jetty), for example C(9.1), C(9.3). + type: str + required: true container_settings: description: - Web app slot container settings. + type: dict suboptions: name: description: - Name of container, for example C(imagename:tag). + type: str + required: true registry_server_url: description: - Container registry server URL, for example C(mydockerregistry.io). + type: str registry_server_user: description: - The container registry server user name. + type: str registry_server_password: description: - The container registry server password. + type: str startup_file: description: - The slot startup file. - This only applies for Linux web app slot. + type: str app_settings: description: - Configure web app slot application settings. Suboptions are in key value pair format. + type: dict purge_app_settings: description: - Purge any existing application settings. Replace slot application settings with app_settings. @@ -137,13 +165,16 @@ options: deployment_source: description: - Deployment source for git. + type: dict suboptions: url: description: - Repository URL of deployment source. + type: str branch: description: - The branch name of the repository. + type: str app_state: description: - Start/Stop/Restart the slot. @@ -154,13 +185,14 @@ options: - restarted default: started state: - description: - - State of the Web App deployment slot. - - Use C(present) to create or update a slot and C(absent) to delete it. - default: present - choices: - - absent - - present + description: + - State of the Web App deployment slot. + - Use C(present) to create or update a slot and C(absent) to delete it. + default: present + type: str + choices: + - absent + - present extends_documentation_fragment: - azure.azcollection.azure @@ -172,46 +204,46 @@ author: ''' EXAMPLES = ''' - - name: Create a webapp slot - azure_rm_webappslot: - resource_group: myResourceGroup - webapp_name: myJavaWebApp - name: stage - configuration_source: myJavaWebApp - app_settings: - testkey: testvalue - - - name: swap the slot with production slot - azure_rm_webappslot: - resource_group: myResourceGroup - webapp_name: myJavaWebApp - name: stage - swap: - action: swap - - - name: stop the slot - azure_rm_webappslot: - resource_group: myResourceGroup - webapp_name: myJavaWebApp - name: stage - app_state: stopped - - - name: udpate a webapp slot app settings - azure_rm_webappslot: - resource_group: myResourceGroup - webapp_name: myJavaWebApp - name: stage - app_settings: - testkey: testvalue2 - - - name: udpate a webapp slot frameworks - azure_rm_webappslot: - resource_group: myResourceGroup - webapp_name: myJavaWebApp - name: stage - frameworks: - - name: "node" - version: "10.1" +- name: Create a webapp slot + azure_rm_webappslot: + resource_group: myResourceGroup + webapp_name: myJavaWebApp + name: stage + configuration_source: myJavaWebApp + app_settings: + testkey: testvalue + +- name: swap the slot with production slot + azure_rm_webappslot: + resource_group: myResourceGroup + webapp_name: myJavaWebApp + name: stage + swap: + action: swap + +- name: stop the slot + azure_rm_webappslot: + resource_group: myResourceGroup + webapp_name: myJavaWebApp + name: stage + app_state: stopped + +- name: udpate a webapp slot app settings + azure_rm_webappslot: + resource_group: myResourceGroup + webapp_name: myJavaWebApp + name: stage + app_settings: + testkey: testvalue2 + +- name: udpate a webapp slot frameworks + azure_rm_webappslot: + resource_group: myResourceGroup + webapp_name: myJavaWebApp + name: stage + frameworks: + - name: "node" + version: "10.1" ''' RETURN = ''' @@ -223,7 +255,6 @@ id: sample: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Web/sites/testapp/slots/stage1 ''' -import time from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappvnetconnection.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappvnetconnection.py index 4b55a93f4..198273351 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappvnetconnection.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappvnetconnection.py @@ -55,26 +55,26 @@ author: ''' EXAMPLES = ''' - - name: Configure web app with virtual network - azure.azcollection.azure_rm_webappvnetconnection: - name: "MyWebapp" - resource_group: "MyResourceGroup" - vnet_name: "MyVnetName" - subnet: "MySubnetName" - - - name: Configure web app with virtual network in different resource group - azure.azcollection.azure_rm_webappvnetconnection: - name: "MyWebapp" - resource_group: "MyResourceGroup" - vnet_name: "MyVnetName" - subnet: "MySubnetName" - vnet_resource_group: "MyOtherResourceGroup" - - - name: Delete web app virtual network - azure.azcollection.azure_rm_webappvnetconnection: - name: "MyWebapp" - resource_group: "MyResourceGroup" - state: "absent" +- name: Configure web app with virtual network + azure.azcollection.azure_rm_webappvnetconnection: + name: "MyWebapp" + resource_group: "MyResourceGroup" + vnet_name: "MyVnetName" + subnet: "MySubnetName" + +- name: Configure web app with virtual network in different resource group + azure.azcollection.azure_rm_webappvnetconnection: + name: "MyWebapp" + resource_group: "MyResourceGroup" + vnet_name: "MyVnetName" + subnet: "MySubnetName" + vnet_resource_group: "MyOtherResourceGroup" + +- name: Delete web app virtual network + azure.azcollection.azure_rm_webappvnetconnection: + name: "MyWebapp" + resource_group: "MyResourceGroup" + state: "absent" ''' RETURN = ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappvnetconnection_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappvnetconnection_info.py index 8ad772918..c114b63ff 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappvnetconnection_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webappvnetconnection_info.py @@ -39,10 +39,10 @@ author: ''' EXAMPLES = ''' - - name: Get web app virtual network connection - azure_rm_webappvnetconnection_info: - name: "MyWebapp" - resource_group: "MyResourceGroup" +- name: Get web app virtual network connection + azure_rm_webappvnetconnection_info: + name: "MyWebapp" + resource_group: "MyResourceGroup" ''' RETURN = ''' |