From 649a3bd1329647145d1901a7e709ac89992d3a93 Mon Sep 17 00:00:00 2001 From: Ross Bender Date: Wed, 11 May 2022 21:10:41 -0500 Subject: [PATCH 1/6] update azure.mgmt.web to latest --- plugins/module_utils/azure_rm_common.py | 7 +- plugins/modules/azure_rm_appserviceplan.py | 27 ++--- .../modules/azure_rm_appserviceplan_info.py | 13 +-- plugins/modules/azure_rm_functionapp.py | 38 +++---- plugins/modules/azure_rm_functionapp_info.py | 13 +-- plugins/modules/azure_rm_webapp.py | 82 ++++++-------- plugins/modules/azure_rm_webapp_info.py | 27 +++-- plugins/modules/azure_rm_webappslot.py | 105 ++++++++++-------- requirements-azure.txt | 2 +- 9 files changed, 147 insertions(+), 167 deletions(-) diff --git a/plugins/module_utils/azure_rm_common.py b/plugins/module_utils/azure_rm_common.py index 9599417c2..82837e762 100644 --- a/plugins/module_utils/azure_rm_common.py +++ b/plugins/module_utils/azure_rm_common.py @@ -103,7 +103,7 @@ def default_api_version(self): 'SearchManagementClient': '2020-08-01', 'StorageManagementClient': '2021-06-01', 'SubscriptionClient': '2019-11-01', - 'WebSiteManagementClient': '2018-02-01', + 'WebSiteManagementClient': '2021-03-01', 'PostgreSQLManagementClient': '2017-12-01', 'MySQLManagementClient': '2017-12-01', 'MariaDBManagementClient': '2019-03-01', @@ -357,7 +357,7 @@ def normalize_location_name(name): }, 'WebSiteManagementClient': { 'package_name': 'web', - 'expected_version': '0.41.0' + 'expected_version': '6.1.0' }, 'TrafficManagerManagementClient': { 'package_name': 'trafficmanager', @@ -1138,7 +1138,8 @@ def web_client(self): if not self._web_client: self._web_client = self.get_mgmt_svc_client(WebSiteManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - api_version='2018-02-01') + is_track2=True, + api_version='2021-03-01') return self._web_client @property diff --git a/plugins/modules/azure_rm_appserviceplan.py b/plugins/modules/azure_rm_appserviceplan.py index 0e67380c7..2c0e883bf 100644 --- a/plugins/modules/azure_rm_appserviceplan.py +++ b/plugins/modules/azure_rm_appserviceplan.py @@ -103,13 +103,10 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: - from msrestazure.azure_exceptions import CloudError - from msrest.polling import LROPoller + from azure.core.exceptions import ResourceNotFoundError + from azure.core.polling import LROPoller from msrestazure.azure_operation import AzureOperationPoller - from msrest.serialization import Model - from azure.mgmt.web.models import ( - app_service_plan, AppServicePlan, SkuDescription - ) + from azure.mgmt.web.models import AppServicePlan, SkuDescription except ImportError: # This is handled in azure_rm_common pass @@ -309,13 +306,13 @@ def get_plan(self): self.log("Get App Service Plan {0}".format(self.name)) try: - response = self.web_client.app_service_plans.get(self.resource_group, self.name) + response = self.web_client.app_service_plans.get(resource_group_name=self.resource_group, name=self.name) if response: self.log("Response : {0}".format(response)) self.log("App Service Plan : {0} found".format(response.name)) return appserviceplan_to_dict(response) - except CloudError as ex: + except ResourceNotFoundError: self.log("Didn't find app service plan {0} in resource group {1}".format(self.name, self.resource_group)) return False @@ -336,7 +333,9 @@ def create_or_update_plan(self): plan_def = AppServicePlan( location=self.location, app_service_plan_name=self.name, sku=sku_def, reserved=self.is_linux, tags=self.tags if self.tags else None) - response = self.web_client.app_service_plans.create_or_update(self.resource_group, self.name, plan_def) + response = self.web_client.app_service_plans.begin_create_or_update(resource_group_name=self.resource_group, + name=self.name, + app_service_plan=plan_def) if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): response = self.get_poller_result(response) @@ -344,7 +343,7 @@ def create_or_update_plan(self): self.log("Response : {0}".format(response)) return appserviceplan_to_dict(response) - except CloudError as ex: + except Exception as ex: self.fail("Failed to create app service plan {0} in resource group {1}: {2}".format(self.name, self.resource_group, str(ex))) def delete_plan(self): @@ -355,12 +354,10 @@ def delete_plan(self): ''' self.log("Deleting the App service plan {0}".format(self.name)) try: - response = self.web_client.app_service_plans.delete(resource_group_name=self.resource_group, - name=self.name) - except CloudError as e: + self.web_client.app_service_plans.delete(resource_group_name=self.resource_group, name=self.name) + except ResourceNotFoundError as e: self.log('Error attempting to delete App service plan.') - self.fail( - "Error deleting the App service plan : {0}".format(str(e))) + self.fail("Error deleting the App service plan : {0}".format(str(e))) return True diff --git a/plugins/modules/azure_rm_appserviceplan_info.py b/plugins/modules/azure_rm_appserviceplan_info.py index 85e0d2998..826ecc175 100644 --- a/plugins/modules/azure_rm_appserviceplan_info.py +++ b/plugins/modules/azure_rm_appserviceplan_info.py @@ -117,8 +117,7 @@ sample: 1 ''' try: - from msrestazure.azure_exceptions import CloudError - from azure.common import AzureMissingResourceHttpError, AzureHttpError + from azure.core.exceptions import ResourceNotFoundError except Exception: # This is handled in azure_rm_common pass @@ -174,8 +173,8 @@ def list_by_name(self): result = [] try: - item = self.web_client.app_service_plans.get(self.resource_group, self.name) - except CloudError: + item = self.web_client.app_service_plans.get(resource_group_name=self.resource_group, name=self.name) + except ResourceNotFoundError: pass if item and self.has_tags(item.tags, self.tags): @@ -187,8 +186,8 @@ def list_by_name(self): def list_by_resource_group(self): self.log('List app service plans in resource groups {0}'.format(self.resource_group)) try: - response = list(self.web_client.app_service_plans.list_by_resource_group(self.resource_group)) - except CloudError as exc: + response = list(self.web_client.app_service_plans.list_by_resource_group(resource_group_name=self.resource_group)) + except Exception as exc: self.fail("Error listing app service plan in resource groups {0} - {1}".format(self.resource_group, str(exc))) results = [] @@ -202,7 +201,7 @@ def list_all(self): self.log('List app service plans in current subscription') try: response = list(self.web_client.app_service_plans.list()) - except CloudError as exc: + except Exception as exc: self.fail("Error listing app service plans: {0}".format(str(exc))) results = [] diff --git a/plugins/modules/azure_rm_functionapp.py b/plugins/modules/azure_rm_functionapp.py index 87415d715..bce42dec9 100644 --- a/plugins/modules/azure_rm_functionapp.py +++ b/plugins/modules/azure_rm_functionapp.py @@ -160,13 +160,8 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: - from msrestazure.azure_exceptions import CloudError - from azure.mgmt.web.models import ( - site_config, app_service_plan, Site, SiteConfig, NameValuePair, SiteSourceControl, - AppServicePlan, SkuDescription - ) - from azure.mgmt.resource.resources import ResourceManagementClient - from msrest.polling import LROPoller + from azure.core.exceptions import ResourceNotFoundError + from azure.mgmt.web.models import Site, SiteConfig, NameValuePair except ImportError: # This is handled in azure_rm_common pass @@ -233,19 +228,16 @@ def exec_module(self, **kwargs): try: resource_group = self.rm_client.resource_groups.get(self.resource_group) - except CloudError: + except Exception: self.fail('Unable to retrieve resource group') self.location = self.location or resource_group.location try: - function_app = self.web_client.web_apps.get( - resource_group_name=self.resource_group, - name=self.name - ) - # Newer SDK versions (0.40.0+) seem to return None if it doesn't exist instead of raising CloudError + function_app = self.web_client.web_apps.get(resource_group_name=self.resource_group, name=self.name) + # Newer SDK versions (0.40.0+) seem to return None if it doesn't exist instead of raising error exists = function_app is not None - except CloudError as exc: + except ResourceNotFoundError as exc: exists = False if self.state == 'absent': @@ -254,12 +246,9 @@ def exec_module(self, **kwargs): self.results['changed'] = True return self.results try: - self.web_client.web_apps.delete( - resource_group_name=self.resource_group, - name=self.name - ) + self.web_client.web_apps.delete(resource_group_name=self.resource_group, name=self.name) self.results['changed'] = True - except CloudError as exc: + except Exception as exc: self.fail('Failure while deleting web app: {0}'.format(exc)) else: self.results['changed'] = False @@ -313,13 +302,12 @@ def exec_module(self, **kwargs): self.results['state'] = function_app.as_dict() elif self.results['changed']: try: - new_function_app = self.web_client.web_apps.create_or_update( - resource_group_name=self.resource_group, - name=self.name, - site_envelope=function_app - ).result() + response = self.web_client.web_apps.begin_create_or_update(resource_group_name=self.resource_group, + name=self.name, + site_envelope=function_app) + new_function_app = self.get_poller_result(response) self.results['state'] = new_function_app.as_dict() - except CloudError as exc: + except Exception as exc: self.fail('Error creating or updating web app: {0}'.format(exc)) return self.results diff --git a/plugins/modules/azure_rm_functionapp_info.py b/plugins/modules/azure_rm_functionapp_info.py index b4a4c042b..3b4904e35 100644 --- a/plugins/modules/azure_rm_functionapp_info.py +++ b/plugins/modules/azure_rm_functionapp_info.py @@ -97,7 +97,7 @@ ''' try: - from msrestazure.azure_exceptions import CloudError + from azure.core.exceptions import ResourceNotFoundError except Exception: # This is handled in azure_rm_common pass @@ -157,11 +157,8 @@ def get_functionapp(self): result = [] try: - function_app = self.web_client.web_apps.get( - self.resource_group, - self.name - ) - except CloudError: + function_app = self.web_client.web_apps.get(resource_group_name=self.resource_group, name=self.name) + except ResourceNotFoundError: pass if function_app and self.has_tags(function_app.tags, self.tags): @@ -172,7 +169,7 @@ def get_functionapp(self): def list_resource_group(self): self.log('List items') try: - response = self.web_client.web_apps.list_by_resource_group(self.resource_group) + response = self.web_client.web_apps.list_by_resource_group(resource_group_name=self.resource_group) except Exception as exc: self.fail("Error listing for resource group {0} - {1}".format(self.resource_group, str(exc))) @@ -185,7 +182,7 @@ def list_resource_group(self): def list_all(self): self.log('List all items') try: - response = self.web_client.web_apps.list_by_resource_group(self.resource_group) + response = self.web_client.web_apps.list_by_resource_group(resource_group_name=self.resource_group) except Exception as exc: self.fail("Error listing all items - {0}".format(str(exc))) diff --git a/plugins/modules/azure_rm_webapp.py b/plugins/modules/azure_rm_webapp.py index 753d3ed6c..f2b61f08b 100644 --- a/plugins/modules/azure_rm_webapp.py +++ b/plugins/modules/azure_rm_webapp.py @@ -332,13 +332,9 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: - from msrestazure.azure_exceptions import CloudError - from msrest.polling import LROPoller - from msrest.serialization import Model - from azure.mgmt.web.models import ( - site_config, app_service_plan, Site, - AppServicePlan, SkuDescription, NameValuePair - ) + from azure.core.exceptions import ResourceNotFoundError + from azure.core.polling import LROPoller + from azure.mgmt.web.models import Site, AppServicePlan, SkuDescription, NameValuePair, SiteSourceControl except ImportError: # This is handled in azure_rm_common pass @@ -889,20 +885,19 @@ def create_update_webapp(self): skip_dns_registration = self.dns_registration force_dns_registration = None if self.dns_registration is None else not self.dns_registration - response = self.web_client.web_apps.create_or_update(resource_group_name=self.resource_group, - name=self.name, - site_envelope=self.site, - skip_dns_registration=skip_dns_registration, - skip_custom_domain_verification=self.skip_custom_domain_verification, - force_dns_registration=force_dns_registration, - ttl_in_seconds=self.ttl_in_seconds) + response = self.web_client.web_apps.begin_create_or_update(resource_group_name=self.resource_group, + name=self.name, + site_envelope=self.site, + skip_dns_registration=skip_dns_registration, + skip_custom_domain_verification=self.skip_custom_domain_verification, + force_dns_registration=force_dns_registration, + ttl_in_seconds=self.ttl_in_seconds) 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 Web App instance.') - self.fail( - "Error creating the Web App instance: {0}".format(str(exc))) + self.fail("Error creating the Web App instance: {0}".format(str(exc))) return webapp_to_dict(response) def delete_webapp(self): @@ -913,12 +908,10 @@ def delete_webapp(self): ''' self.log("Deleting the Web App instance {0}".format(self.name)) try: - response = self.web_client.web_apps.delete(resource_group_name=self.resource_group, - name=self.name) - except CloudError as e: + self.web_client.web_apps.delete(resource_group_name=self.resource_group, name=self.name) + except Exception as e: self.log('Error attempting to delete the Web App instance.') - self.fail( - "Error deleting the Web App instance: {0}".format(str(e))) + self.fail("Error deleting the Web App instance: {0}".format(str(e))) return True @@ -934,20 +927,18 @@ def get_webapp(self): response = None try: - response = self.web_client.web_apps.get(resource_group_name=self.resource_group, - name=self.name) + response = self.web_client.web_apps.get(resource_group_name=self.resource_group, name=self.name) - # Newer SDK versions (0.40.0+) seem to return None if it doesn't exist instead of raising CloudError + # Newer SDK versions (0.40.0+) seem to return None if it doesn't exist instead of raising error if response is not None: self.log("Response : {0}".format(response)) self.log("Web App instance : {0} found".format(response.name)) return webapp_to_dict(response) - except CloudError as ex: + except ResourceNotFoundError: pass - self.log("Didn't find web app {0} in resource group {1}".format( - self.name, self.resource_group)) + self.log("Didn't find web app {0} in resource group {1}".format(self.name, self.resource_group)) return False @@ -963,13 +954,13 @@ def get_app_service_plan(self): resource_group_name=self.plan['resource_group'], name=self.plan['name']) - # Newer SDK versions (0.40.0+) seem to return None if it doesn't exist instead of raising CloudError + # Newer SDK versions (0.40.0+) seem to return None if it doesn't exist instead of raising error if response is not None: self.log("Response : {0}".format(response)) self.log("App Service Plan : {0} found".format(response.name)) return appserviceplan_to_dict(response) - except CloudError as ex: + except ResourceNotFoundError: pass self.log("Didn't find app service plan {0} in resource group {1}".format( @@ -993,8 +984,8 @@ def create_app_service_plan(self): plan_def = AppServicePlan( location=self.plan['location'], app_service_plan_name=self.plan['name'], sku=sku_def, reserved=(self.plan.get('is_linux', None))) - poller = self.web_client.app_service_plans.create_or_update( - self.plan['resource_group'], self.plan['name'], plan_def) + poller = self.web_client.app_service_plans.begin_create_or_update( + resource_group_name=self.plan['resource_group'], name=self.plan['name'], app_service_plan=plan_def) if isinstance(poller, LROPoller): response = self.get_poller_result(poller) @@ -1002,7 +993,7 @@ def create_app_service_plan(self): self.log("Response : {0}".format(response)) return appserviceplan_to_dict(response) - except CloudError as ex: + except Exception as ex: self.fail("Failed to create app service plan {0} in resource group {1}: {2}".format( self.plan['name'], self.plan['resource_group'], str(ex))) @@ -1014,13 +1005,11 @@ def list_app_settings(self): self.log("List application setting") try: - - response = self.web_client.web_apps.list_application_settings( - resource_group_name=self.resource_group, name=self.name) + response = self.web_client.web_apps.list_application_settings(resource_group_name=self.resource_group, name=self.name) self.log("Response : {0}".format(response)) return response.properties - except CloudError as ex: + except Exception as ex: self.fail("Failed to list application settings for web app {0} in resource group {1}: {2}".format( self.name, self.resource_group, str(ex))) @@ -1033,11 +1022,11 @@ def update_app_settings(self): try: response = self.web_client.web_apps.update_application_settings( - resource_group_name=self.resource_group, name=self.name, properties=self.app_settings_strDic) + resource_group_name=self.resource_group, name=self.name, app_settings=self.app_settings_strDic) self.log("Response : {0}".format(response)) return response - except CloudError as ex: + except Exception as ex: self.fail("Failed to update application settings for web app {0} in resource group {1}: {2}".format( self.name, self.resource_group, str(ex))) @@ -1055,12 +1044,16 @@ def create_or_update_source_control(self): self.deployment_source['is_mercurial'] = False try: - response = self.web_client.web_client.create_or_update_source_control( - self.resource_group, self.name, self.deployment_source) + site_source_control = SiteSourceControl( + repo_url=self.deployment_source.get('url'), + branch=self.deployment_source.get('branch') + ) + response = self.web_client.web_apps.begin_create_or_update_source_control( + resource_group_name=self.resource_group, name=self.name, site_source_control=site_source_control) self.log("Response : {0}".format(response)) return response.as_dict() - except CloudError as ex: + except Exception: self.fail("Failed to update site source control for web app {0} in resource group {1}".format( self.name, self.resource_group)) @@ -1072,13 +1065,12 @@ def get_webapp_configuration(self): self.log("Get web app configuration") try: - response = self.web_client.web_apps.get_configuration( resource_group_name=self.resource_group, name=self.name) self.log("Response : {0}".format(response)) return response - except CloudError as ex: + except ResourceNotFoundError as ex: self.log("Failed to get configuration for web app {0} in resource group {1}: {2}".format( self.name, self.resource_group, str(ex))) @@ -1102,7 +1094,7 @@ def set_webapp_state(self, appstate): self.log("Response : {0}".format(response)) return response - except CloudError as ex: + except Exception as ex: request_id = ex.request_id if ex.request_id else '' self.log("Failed to {0} web app {1} in resource group {2}, request_id {3} - {4}".format( appstate, self.name, self.resource_group, request_id, str(ex))) diff --git a/plugins/modules/azure_rm_webapp_info.py b/plugins/modules/azure_rm_webapp_info.py index aa26cadd4..9e862daeb 100644 --- a/plugins/modules/azure_rm_webapp_info.py +++ b/plugins/modules/azure_rm_webapp_info.py @@ -238,9 +238,8 @@ sample: { tag1: abc } ''' try: - from msrestazure.azure_exceptions import CloudError - from msrest.polling import LROPoller - from azure.common import AzureMissingResourceHttpError, AzureHttpError + from azure.core.exceptions import ResourceNotFoundError + from azure.core.polling import LROPoller except Exception: # This is handled in azure_rm_common pass @@ -305,8 +304,8 @@ def list_by_name(self): result = [] try: - item = self.web_client.web_apps.get(self.resource_group, self.name) - except CloudError: + item = self.web_client.web_apps.get(resource_group_name=self.resource_group, name=self.name) + except ResourceNotFoundError: pass if item and self.has_tags(item.tags, self.tags): @@ -318,8 +317,8 @@ def list_by_name(self): def list_by_resource_group(self): self.log('List web apps in resource groups {0}'.format(self.resource_group)) try: - response = list(self.web_client.web_apps.list_by_resource_group(self.resource_group)) - except CloudError as exc: + response = list(self.web_client.web_apps.list_by_resource_group(resource_group_name=self.resource_group)) + except Exception as exc: request_id = exc.request_id if exc.request_id else '' self.fail("Error listing web apps in resource groups {0}, request id: {1} - {2}".format(self.resource_group, request_id, str(exc))) @@ -334,7 +333,7 @@ def list_all(self): self.log('List web apps in current subscription') try: response = list(self.web_client.web_apps.list()) - except CloudError as exc: + except Exception as exc: request_id = exc.request_id if exc.request_id else '' self.fail("Error listing web apps, request id {0} - {1}".format(request_id, str(exc))) @@ -352,7 +351,7 @@ def list_webapp_configuration(self, resource_group, name): try: response = self.web_client.web_apps.get_configuration(resource_group_name=resource_group, name=name) - except CloudError as ex: + except Exception as ex: request_id = ex.request_id if ex.request_id else '' self.fail('Error getting web app {0} configuration, request id {1} - {2}'.format(name, request_id, str(ex))) @@ -365,7 +364,7 @@ def list_webapp_appsettings(self, resource_group, name): try: response = self.web_client.web_apps.list_application_settings(resource_group_name=resource_group, name=name) - except CloudError as ex: + except Exception as ex: request_id = ex.request_id if ex.request_id else '' self.fail('Error getting web app {0} app settings, request id {1} - {2}'.format(name, request_id, str(ex))) @@ -374,10 +373,10 @@ def list_webapp_appsettings(self, resource_group, name): def get_publish_credentials(self, resource_group, name): self.log('Get web app {0} publish credentials'.format(name)) try: - poller = self.web_client.web_apps.list_publishing_credentials(resource_group, name) + poller = self.web_client.web_apps.begin_list_publishing_credentials(resource_group_name=resource_group, name=name) if isinstance(poller, LROPoller): response = self.get_poller_result(poller) - except CloudError as ex: + except Exception as ex: request_id = ex.request_id if ex.request_id else '' self.fail('Error getting web app {0} publishing credentials - {1}'.format(request_id, str(ex))) return response @@ -404,7 +403,7 @@ def get_webapp_ftp_publish_url(self, resource_group, name): if profile['@publishMethod'] == 'FTP': url = profile['@publishUrl'] - except CloudError as ex: + except Exception: self.fail('Error getting web app {0} app settings'.format(name)) return url @@ -417,7 +416,7 @@ def get_curated_webapp(self, resource_group, name, webapp): app_settings = self.list_webapp_appsettings(resource_group, name) publish_cred = self.get_publish_credentials(resource_group, name) ftp_publish_url = self.get_webapp_ftp_publish_url(resource_group, name) - except CloudError as ex: + except Exception: pass return self.construct_curated_webapp(webapp=pip, configuration=site_config, diff --git a/plugins/modules/azure_rm_webappslot.py b/plugins/modules/azure_rm_webappslot.py index 602b414ad..def74969b 100644 --- a/plugins/modules/azure_rm_webappslot.py +++ b/plugins/modules/azure_rm_webappslot.py @@ -227,13 +227,9 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: - from msrestazure.azure_exceptions import CloudError - from msrest.polling import LROPoller - from msrest.serialization import Model - from azure.mgmt.web.models import ( - site_config, app_service_plan, Site, - AppServicePlan, SkuDescription, NameValuePair - ) + from azure.core.exceptions import ResourceNotFoundError + from azure.core.polling import LROPoller + from azure.mgmt.web.models import Site, NameValuePair, SiteSourceControl, CsmSlotEntity except ImportError: # This is handled in azure_rm_common pass @@ -716,14 +712,14 @@ def create_update_slot(self): "Creating / Updating the Web App slot {0}".format(self.name)) try: - response = self.web_client.web_apps.create_or_update_slot(resource_group_name=self.resource_group, - slot=self.name, - name=self.webapp_name, - site_envelope=self.site) + response = self.web_client.web_apps.begin_create_or_update_slot(resource_group_name=self.resource_group, + slot=self.name, + name=self.webapp_name, + site_envelope=self.site) 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 Web App slot instance.') self.fail("Error creating the Web App slot: {0}".format(str(exc))) return slot_to_dict(response) @@ -736,10 +732,10 @@ def delete_slot(self): ''' self.log("Deleting the Web App slot {0}".format(self.name)) try: - response = self.web_client.web_apps.delete_slot(resource_group_name=self.resource_group, - name=self.webapp_name, - slot=self.name) - except CloudError as e: + self.web_client.web_apps.delete_slot(resource_group_name=self.resource_group, + name=self.webapp_name, + slot=self.name) + except Exception as e: self.log('Error attempting to delete the Web App slot.') self.fail( "Error deleting the Web App slots: {0}".format(str(e))) @@ -761,13 +757,13 @@ def get_webapp(self): response = self.web_client.web_apps.get(resource_group_name=self.resource_group, name=self.webapp_name) - # Newer SDK versions (0.40.0+) seem to return None if it doesn't exist instead of raising CloudError + # Newer SDK versions (0.40.0+) seem to return None if it doesn't exist instead of raising error if response is not None: self.log("Response : {0}".format(response)) self.log("Web App instance : {0} found".format(response.name)) return webapp_to_dict(response) - except CloudError as ex: + except ResourceNotFoundError: pass self.log("Didn't find web app {0} in resource group {1}".format( @@ -791,13 +787,13 @@ def get_slot(self): name=self.webapp_name, slot=self.name) - # Newer SDK versions (0.40.0+) seem to return None if it doesn't exist instead of raising CloudError + # Newer SDK versions (0.40.0+) seem to return None if it doesn't exist instead of raising error if response is not None: self.log("Response : {0}".format(response)) self.log("Web App slot: {0} found".format(response.name)) return slot_to_dict(response) - except CloudError as ex: + except ResourceNotFoundError: pass self.log("Does not find web app slot {0} in resource group {1}".format(self.name, self.resource_group)) @@ -812,13 +808,12 @@ def list_app_settings(self): self.log("List webapp application setting") try: - response = self.web_client.web_apps.list_application_settings( resource_group_name=self.resource_group, name=self.webapp_name) self.log("Response : {0}".format(response)) return response.properties - except CloudError as ex: + except Exception as ex: self.fail("Failed to list application settings for web app {0} in resource group {1}: {2}".format( self.name, self.resource_group, str(ex))) @@ -830,13 +825,12 @@ def list_app_settings_slot(self, slot_name): self.log("List application setting") try: - response = self.web_client.web_apps.list_application_settings_slot( resource_group_name=self.resource_group, name=self.webapp_name, slot=slot_name) self.log("Response : {0}".format(response)) return response.properties - except CloudError as ex: + except Exception as ex: self.fail("Failed to list application settings for web app slot {0} in resource group {1}: {2}".format( self.name, self.resource_group, str(ex))) @@ -860,7 +854,7 @@ def update_app_settings_slot(self, slot_name=None, app_settings=None): self.log("Response : {0}".format(response)) return response.as_dict() - except CloudError as ex: + except Exception as ex: self.fail("Failed to update application settings for web app slot {0} in resource group {1}: {2}".format( self.name, self.resource_group, str(ex))) @@ -880,15 +874,19 @@ def create_or_update_source_control_slot(self): self.deployment_source['is_mercurial'] = False try: - response = self.web_client.web_client.create_or_update_source_control_slot( + site_source_control = SiteSourceControl( + repo_url=self.deployment_source.get('url'), + branch=self.deployment_source.get('branch') + ) + response = self.web_client.web_client.begin_create_or_update_source_control_slot( resource_group_name=self.resource_group, name=self.webapp_name, - site_source_control=self.deployment_source, + site_source_control=site_source_control, slot=self.name) self.log("Response : {0}".format(response)) return response.as_dict() - except CloudError as ex: + except Exception as ex: self.fail("Failed to update site source control for web app slot {0} in resource group {1}: {2}".format( self.name, self.resource_group, str(ex))) @@ -900,13 +898,12 @@ def get_configuration(self): self.log("Get web app configuration") try: - response = self.web_client.web_apps.get_configuration( resource_group_name=self.resource_group, name=self.webapp_name) self.log("Response : {0}".format(response)) return response - except CloudError as ex: + except Exception as ex: self.fail("Failed to get configuration for web app {0} in resource group {1}: {2}".format( self.webapp_name, self.resource_group, str(ex))) @@ -918,13 +915,12 @@ def get_configuration_slot(self, slot_name): self.log("Get web app slot configuration") try: - response = self.web_client.web_apps.get_configuration_slot( resource_group_name=self.resource_group, name=self.webapp_name, slot=slot_name) self.log("Response : {0}".format(response)) return response - except CloudError as ex: + except Exception as ex: self.fail("Failed to get configuration for web app slot {0} in resource group {1}: {2}".format( slot_name, self.resource_group, str(ex))) @@ -940,13 +936,12 @@ def update_configuration_slot(self, slot_name=None, site_config=None): if site_config is None: site_config = self.site_config try: - response = self.web_client.web_apps.update_configuration_slot( resource_group_name=self.resource_group, name=self.webapp_name, slot=slot_name, site_config=site_config) self.log("Response : {0}".format(response)) return response - except CloudError as ex: + except Exception as ex: self.fail("Failed to update configuration for web app slot {0} in resource group {1}: {2}".format( slot_name, self.resource_group, str(ex))) @@ -968,7 +963,7 @@ def set_state_slot(self, appstate): self.log("Response : {0}".format(response)) return response - except CloudError as ex: + except Exception as ex: request_id = ex.request_id if ex.request_id else '' self.fail("Failed to {0} web app slot {1} in resource group {2}, request_id {3} - {4}".format( appstate, self.name, self.resource_group, request_id, str(ex))) @@ -983,28 +978,40 @@ def swap_slot(self): try: if self.swap['action'] == 'swap': if self.swap['target_slot'] is None: - response = self.web_client.web_apps.swap_slot_with_production(resource_group_name=self.resource_group, - name=self.webapp_name, - target_slot=self.name, - preserve_vnet=self.swap['preserve_vnet']) + slot_swap_entity = CsmSlotEntity( + target_slot=self.name, + preserve_vnet=self.swap['preserve_vnet'] + ) + response = self.web_client.web_apps.begin_swap_slot_with_production(resource_group_name=self.resource_group, + name=self.webapp_name, + slot_swap_entity=slot_swap_entity) else: - response = self.web_client.web_apps.swap_slot_slot(resource_group_name=self.resource_group, - name=self.webapp_name, - slot=self.name, - target_slot=self.swap['target_slot'], - preserve_vnet=self.swap['preserve_vnet']) + slot_swap_entity = CsmSlotEntity( + target_slot=self.swap['target_slot'], + preserve_vnet=self.swap['preserve_vnet'] + ) + response = self.web_client.web_apps.begin_swap_slot(resource_group_name=self.resource_group, + name=self.webapp_name, + slot=self.name, + slot_swap_entity=slot_swap_entity) elif self.swap['action'] == 'preview': if self.swap['target_slot'] is None: + slot_swap_entity = CsmSlotEntity( + target_slot=self.name, + preserve_vnet=self.swap['preserve_vnet'] + ) response = self.web_client.web_apps.apply_slot_config_to_production(resource_group_name=self.resource_group, name=self.webapp_name, - target_slot=self.name, - preserve_vnet=self.swap['preserve_vnet']) + slot_swap_entity=slot_swap_entity) else: + slot_swap_entity = CsmSlotEntity( + target_slot=self.swap['target_slot'], + preserve_vnet=self.swap['preserve_vnet'] + ) response = self.web_client.web_apps.apply_slot_configuration_slot(resource_group_name=self.resource_group, name=self.webapp_name, slot=self.name, - target_slot=self.swap['target_slot'], - preserve_vnet=self.swap['preserve_vnet']) + slot_swap_entity=slot_swap_entity) elif self.swap['action'] == 'reset': if self.swap['target_slot'] is None: response = self.web_client.web_apps.reset_production_slot_config(resource_group_name=self.resource_group, @@ -1020,7 +1027,7 @@ def swap_slot(self): self.log("Response : {0}".format(response)) return response - except CloudError as ex: + except Exception as ex: self.fail("Failed to swap web app slot {0} in resource group {1}: {2}".format(self.name, self.resource_group, str(ex))) def clone_slot(self): diff --git a/requirements-azure.txt b/requirements-azure.txt index 193ee4fd6..60f4b7b35 100644 --- a/requirements-azure.txt +++ b/requirements-azure.txt @@ -30,7 +30,7 @@ azure-mgmt-servicebus==0.5.3 azure-mgmt-sql==3.0.1 azure-mgmt-storage==19.0.0 azure-mgmt-trafficmanager==0.50.0 -azure-mgmt-web==0.41.0 +azure-mgmt-web==6.1.0 azure-nspkg==2.0.0 azure-storage==0.35.1 msrest==0.6.21 From c025e9eb014cb881c66cf57a770253bfa949f8ef Mon Sep 17 00:00:00 2001 From: Ross Bender Date: Fri, 13 May 2022 19:34:22 -0500 Subject: [PATCH 2/6] fix UnboundLocalError error for unassigned var --- plugins/modules/azure_rm_functionapp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/azure_rm_functionapp.py b/plugins/modules/azure_rm_functionapp.py index bce42dec9..cf0bc00b0 100644 --- a/plugins/modules/azure_rm_functionapp.py +++ b/plugins/modules/azure_rm_functionapp.py @@ -268,7 +268,7 @@ def exec_module(self, **kwargs): if self.container_settings.get('registry_server_password'): self.app_settings['DOCKER_REGISTRY_SERVER_PASSWORD'] = self.container_settings.get('registry_server_password') - if not self.plan and function_app: + if not self.plan and exists: self.plan = function_app.server_farm_id if not exists: From 532d2fc71dab481f58e6d23d420e8a96faafa398 Mon Sep 17 00:00:00 2001 From: Ross Bender Date: Sat, 14 May 2022 17:38:03 -0500 Subject: [PATCH 3/6] update modules after sdk changes --- plugins/modules/azure_rm_webapp.py | 47 +++---------------- plugins/modules/azure_rm_webapp_info.py | 12 +++-- plugins/modules/azure_rm_webappslot.py | 8 ++-- .../targets/azure_rm_webapp/tasks/main.yml | 23 +++++---- 4 files changed, 32 insertions(+), 58 deletions(-) diff --git a/plugins/modules/azure_rm_webapp.py b/plugins/modules/azure_rm_webapp.py index e096d0cc0..8cdaa8a0e 100644 --- a/plugins/modules/azure_rm_webapp.py +++ b/plugins/modules/azure_rm_webapp.py @@ -162,20 +162,6 @@ - Configures web site to accept only https requests. type: bool - dns_registration: - description: - - Whether or not the web app hostname is registered with DNS on creation. Set to C(false) to register. - type: bool - - skip_custom_domain_verification: - description: - - Whether or not to skip verification of custom (non *.azurewebsites.net) domains associated with web app. Set to C(true) to skip. - type: bool - - ttl_in_seconds: - description: - - Time to live in seconds for web app default domain name. - app_settings: description: - Configure web app application settings. Suboptions are in key value pair format. @@ -334,7 +320,7 @@ try: from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from azure.mgmt.web.models import Site, AppServicePlan, SkuDescription, NameValuePair, SiteSourceControl + from azure.mgmt.web.models import Site, AppServicePlan, SkuDescription, NameValuePair, SiteSourceControl, StringDictionary except ImportError: # This is handled in azure_rm_common pass @@ -487,18 +473,9 @@ def __init__(self): type='bool', default=True ), - dns_registration=dict( - type='bool' - ), https_only=dict( type='bool' ), - skip_custom_domain_verification=dict( - type='bool' - ), - ttl_in_seconds=dict( - type='int' - ), app_settings=dict( type='dict' ), @@ -526,9 +503,6 @@ def __init__(self): # update in create_or_update as parameters self.client_affinity_enabled = True - self.dns_registration = None - self.skip_custom_domain_verification = None - self.ttl_in_seconds = None self.https_only = None self.tags = None @@ -574,10 +548,7 @@ def __init__(self): # updatable_properties self.updatable_properties = ["client_affinity_enabled", - "force_dns_registration", - "https_only", - "skip_custom_domain_verification", - "ttl_in_seconds"] + "https_only"] self.supported_linux_frameworks = ['ruby', 'php', 'dotnetcore', 'node', 'java'] self.supported_windows_frameworks = ['net_framework', 'php', 'python', 'node', 'java'] @@ -882,16 +853,9 @@ def create_update_webapp(self): "Creating / Updating the Web App instance {0}".format(self.name)) try: - skip_dns_registration = self.dns_registration - force_dns_registration = None if self.dns_registration is None else not self.dns_registration - response = self.web_client.web_apps.begin_create_or_update(resource_group_name=self.resource_group, name=self.name, - site_envelope=self.site, - skip_dns_registration=skip_dns_registration, - skip_custom_domain_verification=self.skip_custom_domain_verification, - force_dns_registration=force_dns_registration, - ttl_in_seconds=self.ttl_in_seconds) + site_envelope=self.site) if isinstance(response, LROPoller): response = self.get_poller_result(response) @@ -1021,8 +985,11 @@ def update_app_settings(self): self.log("Update application setting") try: + settings = StringDictionary( + properties=self.app_settings_strDic + ) response = self.web_client.web_apps.update_application_settings( - resource_group_name=self.resource_group, name=self.name, app_settings=self.app_settings_strDic) + resource_group_name=self.resource_group, name=self.name, app_settings=settings) self.log("Response : {0}".format(response)) return response diff --git a/plugins/modules/azure_rm_webapp_info.py b/plugins/modules/azure_rm_webapp_info.py index 9e862daeb..36b3eb3d3 100644 --- a/plugins/modules/azure_rm_webapp_info.py +++ b/plugins/modules/azure_rm_webapp_info.py @@ -240,6 +240,7 @@ try: from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller + from azure.mgmt.web.models import CsmPublishingProfileOptions except Exception: # This is handled in azure_rm_common pass @@ -387,7 +388,12 @@ def get_webapp_ftp_publish_url(self, resource_group, name): url = None try: - content = self.web_client.web_apps.list_publishing_profile_xml_with_secrets(resource_group_name=resource_group, name=name) + publishing_profile_options = CsmPublishingProfileOptions( + format="Ftp" + ) + content = self.web_client.web_apps.list_publishing_profile_xml_with_secrets(resource_group_name=resource_group, + name=name, + publishing_profile_options=publishing_profile_options) if not content: return url @@ -403,8 +409,8 @@ def get_webapp_ftp_publish_url(self, resource_group, name): if profile['@publishMethod'] == 'FTP': url = profile['@publishUrl'] - except Exception: - self.fail('Error getting web app {0} app settings'.format(name)) + except Exception as ex: + self.fail('Error getting web app {0} app settings - {1}'.format(name, str(ex))) return url diff --git a/plugins/modules/azure_rm_webappslot.py b/plugins/modules/azure_rm_webappslot.py index def74969b..08ca490b0 100644 --- a/plugins/modules/azure_rm_webappslot.py +++ b/plugins/modules/azure_rm_webappslot.py @@ -229,7 +229,7 @@ try: from azure.core.exceptions import ResourceNotFoundError from azure.core.polling import LROPoller - from azure.mgmt.web.models import Site, NameValuePair, SiteSourceControl, CsmSlotEntity + from azure.mgmt.web.models import Site, NameValuePair, SiteSourceControl, CsmSlotEntity, StringDictionary except ImportError: # This is handled in azure_rm_common pass @@ -846,11 +846,13 @@ def update_app_settings_slot(self, slot_name=None, app_settings=None): if app_settings is None: app_settings = self.app_settings_strDic try: + settings = StringDictionary( + properties=self.app_settings + ) response = self.web_client.web_apps.update_application_settings_slot(resource_group_name=self.resource_group, name=self.webapp_name, slot=slot_name, - kind=None, - properties=app_settings) + app_settings=settings) self.log("Response : {0}".format(response)) return response.as_dict() diff --git a/tests/integration/targets/azure_rm_webapp/tasks/main.yml b/tests/integration/targets/azure_rm_webapp/tasks/main.yml index 5dac03c38..bd22208db 100644 --- a/tests/integration/targets/azure_rm_webapp/tasks/main.yml +++ b/tests/integration/targets/azure_rm_webapp/tasks/main.yml @@ -42,17 +42,16 @@ that: output.changed -# enable after webapp_facts merged -# - name: get the web app -# azure_rm_webapp_info: -# resource_group: "{{ resource_group }}" -# name: "{{ win_app_name }}2" -# register: stopped - -# - name: assert web app is stopped -# assert: -# that: -# - stopped.properties.state == "Stopped" +- name: get the web app + azure_rm_webapp_info: + resource_group: "{{ resource_group }}" + name: "{{ win_app_name }}2" + register: stopped + +- name: assert web app is stopped + assert: + that: + - stopped.webapps[0].app_state == "Stopped" - name: Create a windows web app with existing app service plan, try to update some root level params azure_rm_webapp: @@ -106,7 +105,7 @@ that: - output.webapps | length == 1 - output.webapps[0].app_settings | length == 1 - - output.webapps[0].frameworks | length > 1 # there's default frameworks eg net_framework + - output.webapps[0].frameworks | length > 1 # there's default frameworks eg net_framework - name: Update app settings and framework azure_rm_webapp: From aaae0562dfbb174da07b188deb26abb909812ed8 Mon Sep 17 00:00:00 2001 From: Ross Bender Date: Wed, 25 May 2022 08:50:30 -0500 Subject: [PATCH 4/6] remove old param --- tests/integration/targets/azure_rm_webapp/tasks/main.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/integration/targets/azure_rm_webapp/tasks/main.yml b/tests/integration/targets/azure_rm_webapp/tasks/main.yml index bd22208db..b286bfe13 100644 --- a/tests/integration/targets/azure_rm_webapp/tasks/main.yml +++ b/tests/integration/targets/azure_rm_webapp/tasks/main.yml @@ -58,7 +58,6 @@ resource_group: "{{ resource_group }}" name: "{{ win_app_name }}3" plan: "{{ win_plan_name }}" - dns_registration: true https_only: true tags: testwebapptag: test From 94f83e9c67e97b9bbab5bafd654addae3a390cf8 Mon Sep 17 00:00:00 2001 From: Ross Bender Date: Wed, 25 May 2022 13:10:50 -0500 Subject: [PATCH 5/6] update method name after breaking change --- plugins/modules/azure_rm_webappvnetconnection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/azure_rm_webappvnetconnection.py b/plugins/modules/azure_rm_webappvnetconnection.py index 41254ab54..4b55a93f4 100644 --- a/plugins/modules/azure_rm_webappvnetconnection.py +++ b/plugins/modules/azure_rm_webappvnetconnection.py @@ -223,7 +223,7 @@ def delete_vnet_connection(self): def create_or_update_vnet_connection(self, vnet): try: - return self.web_client.web_apps.create_or_update_swift_virtual_network_connection( + return self.web_client.web_apps.create_or_update_swift_virtual_network_connection_with_check( resource_group_name=self.resource_group, name=self.name, connection_envelope=vnet) except Exception as exc: self.fail("Error creating/updating webapp vnet connection {0} (vnet={1}, rg={2}) - {3}".format( From 7765214d912874b9213e2813a3567e192a894b1e Mon Sep 17 00:00:00 2001 From: Ross Bender Date: Fri, 3 Jun 2022 11:44:47 -0500 Subject: [PATCH 6/6] correct change in api behavior for default rules --- plugins/modules/azure_rm_webappaccessrestriction.py | 13 ++++++++++++- .../azure_rm_webappaccessrestriction_info.py | 13 ++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/plugins/modules/azure_rm_webappaccessrestriction.py b/plugins/modules/azure_rm_webappaccessrestriction.py index 46007e899..a8a3f5952 100644 --- a/plugins/modules/azure_rm_webappaccessrestriction.py +++ b/plugins/modules/azure_rm_webappaccessrestriction.py @@ -357,7 +357,18 @@ def to_restriction_obj(self, restriction_dict): ) def to_restriction_dict_list(self, restriction_obj_list): - return [] if not restriction_obj_list else [self.to_restriction_dict(restriction) for restriction in restriction_obj_list] + restrictions = [] + if restriction_obj_list: + for r in restriction_obj_list: + restriction = self.to_restriction_dict(r) + if not self.is_azure_default_restriction(restriction): + restrictions.append(restriction) + + return restrictions + + def is_azure_default_restriction(self, restriction_obj): + return (restriction_obj["action"] == "Allow" and restriction_obj["ip_address"] == "Any" and restriction_obj["priority"] == 1) or \ + (restriction_obj["action"] == "Deny" and restriction_obj["ip_address"] == "Any" and restriction_obj["priority"] == 2147483647) def to_restriction_dict(self, restriction_obj): return dict( diff --git a/plugins/modules/azure_rm_webappaccessrestriction_info.py b/plugins/modules/azure_rm_webappaccessrestriction_info.py index bdfa92b4a..0c3eb3260 100644 --- a/plugins/modules/azure_rm_webappaccessrestriction_info.py +++ b/plugins/modules/azure_rm_webappaccessrestriction_info.py @@ -176,7 +176,18 @@ def set_results(self, site_config): return output def to_restriction_dict_list(self, restriction_obj_list): - return [] if not restriction_obj_list else [self.to_restriction_dict(restriction) for restriction in restriction_obj_list] + restrictions = [] + if restriction_obj_list: + for r in restriction_obj_list: + restriction = self.to_restriction_dict(r) + if not self.is_azure_default_restriction(restriction): + restrictions.append(restriction) + + return restrictions + + def is_azure_default_restriction(self, restriction_obj): + return (restriction_obj["action"] == "Allow" and restriction_obj["ip_address"] == "Any" and restriction_obj["priority"] == 1) or \ + (restriction_obj["action"] == "Deny" and restriction_obj["ip_address"] == "Any" and restriction_obj["priority"] == 2147483647) def to_restriction_dict(self, restriction_obj): return dict(