From 7d3cf7db69fec5e6453a4a092245282d59de4c00 Mon Sep 17 00:00:00 2001 From: Kirstyn Joy Amperiadis Date: Thu, 8 Feb 2024 16:40:58 -0600 Subject: [PATCH 1/5] Use SDK for API calls --- .../cli/command_modules/appservice/custom.py | 148 ++++++++---------- 1 file changed, 64 insertions(+), 84 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/appservice/custom.py b/src/azure-cli/azure/cli/command_modules/appservice/custom.py index 108fd472982..83a11266e04 100644 --- a/src/azure-cli/azure/cli/command_modules/appservice/custom.py +++ b/src/azure-cli/azure/cli/command_modules/appservice/custom.py @@ -1665,68 +1665,46 @@ def update_configuration_polling(cmd, resource_group_name, name, slot, configs): raise CLIError(ex) -def update_flex_functionapp(cmd, resource_group_name, name, functionapp): - from azure.cli.core.commands.client_factory import get_subscription_id - client = web_client_factory(cmd.cli_ctx) - subscription_id = get_subscription_id(cmd.cli_ctx) - url_base = 'subscriptions/{}/resourceGroups/{}/providers/Microsoft.Web/sites/{}?api-version={}' - # TODO: switch to use new api version is available - url = url_base.format(subscription_id, resource_group_name, name, client.DEFAULT_API_VERSION) - request_url = cmd.cli_ctx.cloud.endpoints.resource_manager + url - body = json.dumps(functionapp) - response = send_raw_request(cmd.cli_ctx, "PATCH", request_url, body=body) - return response.json() - - def delete_always_ready_settings(cmd, resource_group_name, name, setting_names): - functionapp = get_raw_functionapp(cmd, resource_group_name, name) - - # TODO: see if this is actually necessary and remove it otherwise - if 'functionAppConfig' not in functionapp["properties"]: - functionapp["properties"]["functionAppConfig"] = {} - if 'scaleAndConcurrency' not in functionapp["properties"]["functionAppConfig"]: - functionapp["properties"]["functionAppConfig"]["scaleAndConcurrency"] = {} - - always_ready_config = functionapp["properties"]["functionAppConfig"]["scaleAndConcurrency"].get("alwaysReady", []) + client = web_client_factory(cmd.cli_ctx) + functionapp = client.web_apps.get(resource_group_name, name) + always_ready_config = functionapp.function_app_config.scale_and_concurrency.always_ready or [] - updated_always_ready_config = [x for x in always_ready_config if x["name"] not in setting_names] + updated_always_ready_config = [x for x in always_ready_config if x.name not in setting_names] - functionapp["properties"]["functionAppConfig"]["scaleAndConcurrency"]["alwaysReady"] = updated_always_ready_config + functionapp.function_app_config.scale_and_concurrency.always_ready = updated_always_ready_config - return update_flex_functionapp(cmd, resource_group_name, name, functionapp) + return _generic_site_operation(cmd.cli_ctx, resource_group_name, name, 'update', None, functionapp) def update_always_ready_settings(cmd, resource_group_name, name, settings): - functionapp = get_raw_functionapp(cmd, resource_group_name, name) - - # TODO: see if this is actually necessary and remove it otherwise - if 'functionAppConfig' not in functionapp["properties"]: - functionapp["properties"]["functionAppConfig"] = {} - if 'scaleAndConcurrency' not in functionapp["properties"]["functionAppConfig"]: - functionapp["properties"]["functionAppConfig"]["scaleAndConcurrency"] = {} + client = web_client_factory(cmd.cli_ctx) + functionapp = client.web_apps.get(resource_group_name, name) + always_ready_config = functionapp.function_app_config.scale_and_concurrency.always_ready or [] - always_ready_config = functionapp["properties"]["functionAppConfig"]["scaleAndConcurrency"].get("alwaysReady", []) + FunctionsAlwaysReadyConfig = cmd.get_models('FunctionsAlwaysReadyConfig') updated_always_ready_dict = _parse_key_value_pairs(settings) updated_always_ready_config = [] for key, value in updated_always_ready_dict.items(): - updated_always_ready_config.append({"name": key, "instanceCount": validate_and_convert_to_int(key, value)}) + updated_always_ready_config.append(FunctionsAlwaysReadyConfig( + name=key, + instance_count=value)) for always_ready_setting in always_ready_config: - if always_ready_setting["name"] not in updated_always_ready_dict: + if always_ready_setting.name not in updated_always_ready_dict: updated_always_ready_config.append(always_ready_setting) - functionapp["properties"]["functionAppConfig"]["scaleAndConcurrency"]["alwaysReady"] = updated_always_ready_config + functionapp.function_app_config.scale_and_concurrency.always_ready = updated_always_ready_config - return update_flex_functionapp(cmd, resource_group_name, name, functionapp) + return _generic_site_operation(cmd.cli_ctx, resource_group_name, name, 'update', None, functionapp) def get_scale_config(cmd, resource_group_name, name): - functionapp = get_raw_functionapp(cmd, resource_group_name, name) - - return functionapp.get("properties", {}).get("functionAppConfig", {}).get( - "scaleAndConcurrency", {}) + client = web_client_factory(cmd.cli_ctx) + functionapp = client.web_apps.get(resource_group_name, name) + return functionapp.function_app_config.scale_and_concurrency def update_scale_config(cmd, resource_group_name, name, maximum_instance_count=None, @@ -1735,34 +1713,40 @@ def update_scale_config(cmd, resource_group_name, name, maximum_instance_count=N raise RequiredArgumentMissingError("usage error: --trigger-type must be used with parameter " "--trigger-settings.") - functionapp = get_raw_functionapp(cmd, resource_group_name, name) - - # TODO: see if this is actually necessary and remove it otherwise - if 'functionAppConfig' not in functionapp["properties"]: - functionapp["properties"]["functionAppConfig"] = {} - if 'scaleAndConcurrency' not in functionapp["properties"]["functionAppConfig"]: - functionapp["properties"]["functionAppConfig"]["scaleAndConcurrency"] = {} + client = web_client_factory(cmd.cli_ctx) + functionapp = client.web_apps.get(resource_group_name, name) + scale_config = functionapp.function_app_config.scale_and_concurrency - scale_config = functionapp["properties"]["functionAppConfig"]["scaleAndConcurrency"] + FunctionsScaleAndConcurrencyTriggers, FunctionsScaleAndConcurrencyTriggersHttp = cmd.get_models( + 'FunctionsScaleAndConcurrencyTriggers', 'FunctionsScaleAndConcurrencyTriggersHttp') if maximum_instance_count: - scale_config["maximumInstanceCount"] = maximum_instance_count + scale_config.maximum_instance_count = maximum_instance_count if instance_memory: - scale_config["instanceMemoryMB"] = instance_memory + scale_config.instance_memory_mb = instance_memory if trigger_type: if not getattr(scale_config, 'triggers', None): - scale_config["triggers"] = {} - if not getattr(scale_config["triggers"], trigger_type, None): - scale_config["triggers"][trigger_type] = {} + scale_config.triggers = FunctionsScaleAndConcurrencyTriggers() + snake_case_trigger_type = _convert_camel_to_snake_case(trigger_type) triggers_dict = _parse_key_value_pairs(trigger_settings) for key, value in triggers_dict.items(): - scale_config["triggers"][trigger_type][key] = validate_and_convert_to_int(key, value) + if snake_case_trigger_type not in scale_config.triggers.__dict__: + raise ValidationError("The trigger type '{}' is not valid.".format(trigger_type)) + if not getattr(scale_config.triggers, snake_case_trigger_type, None): + if snake_case_trigger_type == 'http': + scale_config.triggers.http = FunctionsScaleAndConcurrencyTriggersHttp() + snake_case_key = _convert_camel_to_snake_case(key) + if snake_case_key not in getattr(scale_config.triggers, snake_case_trigger_type).__dict__: + raise ValidationError("The trigger setting '{}' is not valid for the " + "trigger type '{}'".format(key, trigger_type)) - functionapp["properties"]["functionAppConfig"]["scaleAndConcurrency"] = scale_config + setattr(getattr(scale_config.triggers, snake_case_trigger_type), snake_case_key, value) - return update_flex_functionapp(cmd, resource_group_name, name, functionapp) + functionapp.function_app_config.scale_and_concurrency = scale_config + + return _generic_site_operation(cmd.cli_ctx, resource_group_name, name, 'update', None, functionapp) def delete_app_settings(cmd, resource_group_name, name, setting_names, slot=None): @@ -4429,17 +4413,17 @@ def create_functionapp(cmd, resource_group_name, name, storage_account, plan=Non 'userAssignedIdentity.' ) - function_app_config = {} - deployment_storage_auth_config = { - "type": deployment_storage_auth_type - } - function_app_config["deployment"] = { - "storage": { - "type": "blobContainer", - "value": deployment_config_storage_value, - "authentication": deployment_storage_auth_config - } - } + from azure.mgmt.web.models import (FunctionAppConfig, FunctionsDeployment, FunctionsDeploymentStorage, + FunctionsDeploymentStorageAuthentication, FunctionsScaleAndConcurrency, + FunctionsAlwaysReadyConfig) + deployment_storage_auth_config = FunctionsDeploymentStorageAuthentication( + type=deployment_storage_auth_type + ) + deployment_storage_config = FunctionsDeploymentStorage( + type='blobContainer', + value=deployment_config_storage_value, + authentication=deployment_storage_auth_config + ) if deployment_storage_auth_type == 'userAssignedIdentity': deployment_storage_user_assigned_identity = _get_or_create_user_assigned_identity( @@ -4449,25 +4433,29 @@ def create_functionapp(cmd, resource_group_name, name, storage_account, plan=Non deployment_storage_auth_value, flexconsumption_location) deployment_storage_auth_value = deployment_storage_user_assigned_identity.id - deployment_storage_auth_config["userAssignedIdentityResourceId"] = deployment_storage_auth_value + deployment_storage_auth_config.user_assigned_identity_resource_id = deployment_storage_auth_value elif deployment_storage_auth_type == 'storageAccountConnectionString': deployment_storage_conn_string = _get_storage_connection_string(cmd.cli_ctx, deployment_storage) site_config.app_settings.append(NameValuePair(name='DEPLOYMENT_STORAGE_CONNECTION_STRING', value=deployment_storage_conn_string)) deployment_storage_auth_value = 'DEPLOYMENT_STORAGE_CONNECTION_STRING' - deployment_storage_auth_config["storageAccountConnectionStringName"] = deployment_storage_auth_value + deployment_storage_auth_config.storage_account_connection_string_name = deployment_storage_auth_value + + function_app_config = FunctionAppConfig() + functionapp_def.function_app_config = function_app_config + function_app_config.deployment = FunctionsDeployment(storage=deployment_storage_config) always_ready_dict = _parse_key_value_pairs(always_ready_instances) always_ready_config = [] for key, value in always_ready_dict.items(): - always_ready_config.append({"name": key, "instanceCount": validate_and_convert_to_int(key, value)}) + always_ready_config.append(FunctionsAlwaysReadyConfig(name=key, instance_count=value)) - function_app_config["scaleAndConcurrency"] = { - "maximumInstanceCount": maximum_instance_count, - "instanceMemoryMB": instance_memory or DEFAULT_INSTANCE_SIZE, - "alwaysReady": always_ready_config - } + function_app_config.scale_and_concurrency = FunctionsScaleAndConcurrency( + maximum_instance_count=maximum_instance_count, + instance_memory_mb=instance_memory or DEFAULT_INSTANCE_SIZE, + always_ready=always_ready_config + ) if deployment_storage_auth_type == 'userAssignedIdentity': assign_identities = [deployment_storage_auth_value] @@ -4679,14 +4667,6 @@ def create_functionapp(cmd, resource_group_name, name, storage_account, plan=Non elif not disable_app_insights and matched_runtime.app_insights: create_app_insights = True - if flexconsumption_location is not None: - functionapp_def.enable_additional_properties_sending() - existing_properties = functionapp_def.serialize()["properties"] - functionapp_def.additional_properties["properties"] = existing_properties - functionapp_def.additional_properties["properties"]["functionAppConfig"] = function_app_config - # TODO: use following poller if new API version is released - # poller = client.web_apps.begin_create_or_update(resource_group_name, name, functionapp_def, api_version='2023-12-01') - poller = client.web_apps.begin_create_or_update(resource_group_name, name, functionapp_def) functionapp = LongRunningOperation(cmd.cli_ctx)(poller) From b30f0b20612d3f4375314fe980a0f86691817991 Mon Sep 17 00:00:00 2001 From: Kirstyn Joy Amperiadis Date: Fri, 9 Feb 2024 13:51:37 -0600 Subject: [PATCH 2/5] Initialize http triggers object outside of settings loop --- .../azure/cli/command_modules/appservice/custom.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/appservice/custom.py b/src/azure-cli/azure/cli/command_modules/appservice/custom.py index 83a11266e04..0d4e638c3d9 100644 --- a/src/azure-cli/azure/cli/command_modules/appservice/custom.py +++ b/src/azure-cli/azure/cli/command_modules/appservice/custom.py @@ -1730,13 +1730,13 @@ def update_scale_config(cmd, resource_group_name, name, maximum_instance_count=N if not getattr(scale_config, 'triggers', None): scale_config.triggers = FunctionsScaleAndConcurrencyTriggers() snake_case_trigger_type = _convert_camel_to_snake_case(trigger_type) + if snake_case_trigger_type not in scale_config.triggers.__dict__: + raise ValidationError("The trigger type '{}' is not valid.".format(trigger_type)) + if not getattr(scale_config.triggers, snake_case_trigger_type, None): + if snake_case_trigger_type == 'http': + scale_config.triggers.http = FunctionsScaleAndConcurrencyTriggersHttp() triggers_dict = _parse_key_value_pairs(trigger_settings) for key, value in triggers_dict.items(): - if snake_case_trigger_type not in scale_config.triggers.__dict__: - raise ValidationError("The trigger type '{}' is not valid.".format(trigger_type)) - if not getattr(scale_config.triggers, snake_case_trigger_type, None): - if snake_case_trigger_type == 'http': - scale_config.triggers.http = FunctionsScaleAndConcurrencyTriggersHttp() snake_case_key = _convert_camel_to_snake_case(key) if snake_case_key not in getattr(scale_config.triggers, snake_case_trigger_type).__dict__: raise ValidationError("The trigger setting '{}' is not valid for the " From 8a9bb1c9b2ed2a61b7f1b99c4e3dd6e086bbdd5f Mon Sep 17 00:00:00 2001 From: Kirstyn Joy Amperiadis Date: Fri, 23 Feb 2024 10:45:19 -0600 Subject: [PATCH 3/5] Use SDK for runtime config and deployment config --- .../cli/command_modules/appservice/custom.py | 122 ++++++------------ .../cli/command_modules/appservice/utils.py | 9 -- 2 files changed, 42 insertions(+), 89 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/appservice/custom.py b/src/azure-cli/azure/cli/command_modules/appservice/custom.py index 01c88dcd38c..604e43b9aa5 100644 --- a/src/azure-cli/azure/cli/command_modules/appservice/custom.py +++ b/src/azure-cli/azure/cli/command_modules/appservice/custom.py @@ -70,7 +70,7 @@ get_pool_manager, use_additional_properties, get_app_service_plan_from_webapp, get_resource_if_exists, repo_url_to_name, get_token, app_service_plan_exists, is_centauri_functionapp, is_flex_functionapp, - _remove_list_duplicates, get_raw_functionapp) + _remove_list_duplicates) from ._create_util import (zip_contents_from_dir, get_runtime_version_details, create_resource_group, get_app_details, check_resource_group_exists, set_location, get_site_availability, get_profile_username, get_plan_to_use, get_lang_from_content, get_rg_to_use, get_sku_to_use, @@ -672,7 +672,7 @@ def enable_zip_deploy_flex(cmd, resource_group_name, name, src, timeout=None, sl raise ResourceNotFoundError('Failed to fetch scm url for function app') runtime_config = get_runtime_config(cmd, resource_group_name, name) - runtime = runtime_config.get("name", "") + runtime = runtime_config.name build_remote = build_remote or runtime == 'python' zip_url = scm_url + '/api/publish?RemoteBuild={}&Deployer=az_cli'.format(build_remote) @@ -1105,8 +1105,6 @@ def list_function_app(cmd, resource_group_name=None): def show_functionapp(cmd, resource_group_name, name, slot=None): - if is_flex_functionapp(cmd.cli_ctx, resource_group_name, name): - return get_raw_functionapp(cmd, resource_group_name, name) app = _generic_site_operation(cmd.cli_ctx, resource_group_name, name, 'get', slot) if not app: raise ResourceNotFoundError("Unable to find resource'{}', in ResourceGroup '{}'.".format(name, @@ -1572,9 +1570,10 @@ def _get_linux_multicontainer_encoded_config_from_file(file_name): def get_deployment_configs(cmd, resource_group_name, name): - functionapp = get_raw_functionapp(cmd, resource_group_name, name) - return functionapp.get("properties", {}).get("functionAppConfig", {}).get( - "deployment", {}) + client = web_client_factory(cmd.cli_ctx) + functionapp = client.web_apps.get(resource_group_name, name) + + return functionapp.function_app_config.deployment def update_deployment_configs(cmd, resource_group_name, name, # pylint: disable=too-many-branches @@ -1597,37 +1596,13 @@ def update_deployment_configs(cmd, resource_group_name, name, # pylint: disable 'Please try again with --deployment-storage-auth-type set to UserAssignedIdentity.' ) - functionapp = get_raw_functionapp(cmd, resource_group_name, name) - - # TODO: see if this is actually necessary and remove it otherwise - if 'functionAppConfig' not in functionapp["properties"]: - functionapp["properties"]["functionAppConfig"] = {} - if 'deployment' not in functionapp["properties"]["functionAppConfig"]: - functionapp["properties"]["functionAppConfig"]["deployment"] = { - "storage": { - "type": "blobContainer" - } - } + client = web_client_factory(cmd.cli_ctx) + functionapp = client.web_apps.get(resource_group_name, name) - functionapp_deployment_storage = functionapp["properties"]["functionAppConfig"]["deployment"]["storage"] + functionapp_deployment_storage = functionapp.function_app_config.deployment.storage deployment_storage = None - if (functionapp_deployment_storage["value"] is None): - if deployment_storage_name is None: - raise ValidationError("Please provide a values for --deployment-storage-name and " - "--deployment-storage-container-name as function app deployment " - "storage value is not set.") - - if ("authentication" not in functionapp_deployment_storage or - functionapp_deployment_storage["authentication"] is None): - if deployment_storage_auth_type is None: - raise ValidationError("Please provide a value for --deployment-storage-auth-type as " - "function app deployment storage authentication type is not set.") - functionapp_deployment_storage["authentication"] = {"type": "SystemAssignedIdentity", - "userAssignedIdentityResourceId": None, - "storageAccountConnectionStringName": None} - # Storage deployment_config_storage_value = None if (deployment_storage_name is not None): @@ -1641,24 +1616,24 @@ def update_deployment_configs(cmd, resource_group_name, name, # pylint: disable deployment_storage_container_name = deployment_storage_container.name endpoints = deployment_storage.primary_endpoints deployment_config_storage_value = getattr(endpoints, 'blob') + deployment_storage_container_name - functionapp_deployment_storage["value"] = deployment_config_storage_value + functionapp_deployment_storage.value = deployment_config_storage_value # Authentication assign_identities = None if deployment_storage_auth_type is not None: - deployment_storage_auth_config = functionapp_deployment_storage["authentication"] - deployment_storage_auth_config["type"] = deployment_storage_auth_type + deployment_storage_auth_config = functionapp_deployment_storage.authentication + deployment_storage_auth_config.type = deployment_storage_auth_type if deployment_storage_auth_type == 'StorageAccountConnectionString': deployment_storage_conn_string = _get_storage_connection_string(cmd.cli_ctx, deployment_storage) update_app_settings(cmd, resource_group_name, name, ["DEPLOYMENT_STORAGE_CONNECTION_STRING={}".format(deployment_storage_conn_string)]) - deployment_storage_auth_config["userAssignedIdentityResourceId"] = None - deployment_storage_auth_config["storageAccountConnectionStringName"] = \ + deployment_storage_auth_config.user_assigned_identity_resource_id = None + deployment_storage_auth_config.storage_account_connection_string_name = \ "DEPLOYMENT_STORAGE_CONNECTION_STRING" elif deployment_storage_auth_type == 'SystemAssignedIdentity': assign_identities = ['[system]'] - deployment_storage_auth_config["userAssignedIdentityResourceId"] = None - deployment_storage_auth_config["storageAccountConnectionStringName"] = None + deployment_storage_auth_config.user_assigned_identity_resource_id = None + deployment_storage_auth_config.storage_account_connection_string_name = None elif deployment_storage_auth_type == 'UserAssignedIdentity': deployment_storage_user_assigned_identity = _get_or_create_user_assigned_identity( cmd, @@ -1666,19 +1641,16 @@ def update_deployment_configs(cmd, resource_group_name, name, # pylint: disable name, deployment_storage_auth_value, None) - deployment_storage_auth_config["userAssignedIdentityResourceId"] = \ + deployment_storage_auth_config.user_assigned_identity_resource_id = \ deployment_storage_user_assigned_identity.id - deployment_storage_auth_config["storageAccountConnectionStringName"] = None + deployment_storage_auth_config.storage_account_connection_string_name = None assign_identities = [deployment_storage_user_assigned_identity.id] else: raise ValidationError("Invalid value for --deployment-storage-auth-type. Please try " "again with a valid value.") - functionapp["properties"]["functionAppConfig"]["deployment"]["storage"] = functionapp_deployment_storage - result = update_flex_functionapp(cmd, resource_group_name, name, functionapp) + functionapp.function_app_config.deployment.storage = functionapp_deployment_storage - client = web_client_factory(cmd.cli_ctx) - functionapp = client.web_apps.get(resource_group_name, name) if deployment_storage_auth_type == 'UserAssignedIdentity': assign_identity(cmd, resource_group_name, name, assign_identities) if not _has_deployment_storage_role_assignment_on_resource( @@ -1696,8 +1668,7 @@ def update_deployment_configs(cmd, resource_group_name, name, # pylint: disable poller = client.web_apps.begin_create_or_update(resource_group_name, name, functionapp) functionapp = LongRunningOperation(cmd.cli_ctx)(poller) - return result.get("properties", {}).get("functionAppConfig", {}).get( - "deployment", {}) + return functionapp.function_app_config.deployment # for any modifications to the non-optional parameters, adjust the reflection logic accordingly @@ -1810,9 +1781,9 @@ def delete_always_ready_settings(cmd, resource_group_name, name, setting_names): functionapp.function_app_config.scale_and_concurrency.always_ready = updated_always_ready_config - result = _generic_site_operation(cmd.cli_ctx, resource_group_name, name, 'update', None, functionapp) - - return result.function_app_config.scale_and_concurrency + poller = client.web_apps.begin_create_or_update(resource_group_name, name, functionapp) + functionapp = LongRunningOperation(cmd.cli_ctx)(poller) + return functionapp.function_app_config.scale_and_concurrency def get_runtime_config(cmd, resource_group_name, name): @@ -1823,13 +1794,8 @@ def get_runtime_config(cmd, resource_group_name, name): def update_runtime_config(cmd, resource_group_name, name, runtime_version): - functionapp = get_raw_functionapp(cmd, resource_group_name, name) - - # TODO: remove it later - if 'functionAppConfig' not in functionapp["properties"]: - functionapp["properties"]["functionAppConfig"] = {} - if 'runtime' not in functionapp["properties"]["functionAppConfig"]: - functionapp["properties"]["functionAppConfig"]["runtime"] = {} + client = web_client_factory(cmd.cli_ctx) + functionapp = client.web_apps.get(resource_group_name, name) runtime_info = _get_functionapp_runtime_info(cmd, resource_group_name, name, None, True) runtime = runtime_info['app_runtime'] @@ -1847,12 +1813,11 @@ def update_runtime_config(cmd, resource_group_name, name, runtime_version): matched_runtime = runtime_helper.resolve(runtime, runtime_version, functionapp_version, True) version = matched_runtime.version - functionapp["properties"]["functionAppConfig"]["runtime"]["version"] = version - - result = update_flex_functionapp(cmd, resource_group_name, name, functionapp) + functionapp.function_app_config.runtime.version = version - return result.get("properties", {}).get("functionAppConfig", {}).get( - "runtime", {}) + poller = client.web_apps.begin_create_or_update(resource_group_name, name, functionapp) + functionapp = LongRunningOperation(cmd.cli_ctx)(poller) + return functionapp.function_app_config.runtime def update_always_ready_settings(cmd, resource_group_name, name, settings): @@ -1878,9 +1843,9 @@ def update_always_ready_settings(cmd, resource_group_name, name, settings): updated_always_ready_config.append(always_ready_setting) functionapp.function_app_config.scale_and_concurrency.always_ready = updated_always_ready_config - - result = _generic_site_operation(cmd.cli_ctx, resource_group_name, name, 'update', None, functionapp) - return result.function_app_config.scale_and_concurrency + poller = client.web_apps.begin_create_or_update(resource_group_name, name, functionapp) + functionapp = LongRunningOperation(cmd.cli_ctx)(poller) + return functionapp.function_app_config.scale_and_concurrency def get_scale_config(cmd, resource_group_name, name): @@ -1928,9 +1893,9 @@ def update_scale_config(cmd, resource_group_name, name, maximum_instance_count=N functionapp.function_app_config.scale_and_concurrency = scale_config - result = _generic_site_operation(cmd.cli_ctx, resource_group_name, name, 'update', None, functionapp) - - return result.function_app_config.scale_and_concurrency + poller = client.web_apps.begin_create_or_update(resource_group_name, name, functionapp) + functionapp = LongRunningOperation(cmd.cli_ctx)(poller) + return functionapp.function_app_config.scale_and_concurrency def delete_app_settings(cmd, resource_group_name, name, setting_names, slot=None): @@ -4673,13 +4638,13 @@ def create_functionapp(cmd, resource_group_name, name, storage_account, plan=Non runtime_version, functions_version, is_linux) if flexconsumption_location: + from azure.mgmt.web.models import FunctionsRuntime runtime = matched_runtime.name version = matched_runtime.version - runtime_config = { - "name": runtime, - "version": version - } - function_app_config["runtime"] = runtime_config + function_app_config.runtime = FunctionsRuntime( + name=runtime, + version=version + ) SiteConfigPropertiesDictionary = cmd.get_models('SiteConfigPropertiesDictionary') @@ -4899,9 +4864,6 @@ def create_functionapp(cmd, resource_group_name, name, storage_account, plan=Non role, None, scope) functionapp.identity = identity - if flexconsumption_location is not None: - return get_raw_functionapp(cmd, resource_group_name, name) - return functionapp @@ -7824,8 +7786,8 @@ def _get_functionapp_runtime_info(cmd, resource_group, name, slot, is_linux): # if is_flex_functionapp(cmd.cli_ctx, resource_group, name): app_runtime_config = get_runtime_config(cmd, resource_group, name) - app_runtime = app_runtime_config.get("name", "") - app_runtime_version = app_runtime_config.get("version", "") + app_runtime = app_runtime_config.name + app_runtime_version = app_runtime_config.version return _get_functionapp_runtime_info_helper(cmd, app_runtime, app_runtime_version, functionapp_version, None) if is_linux: diff --git a/src/azure-cli/azure/cli/command_modules/appservice/utils.py b/src/azure-cli/azure/cli/command_modules/appservice/utils.py index 0724636be0e..f5be2489e8c 100644 --- a/src/azure-cli/azure/cli/command_modules/appservice/utils.py +++ b/src/azure-cli/azure/cli/command_modules/appservice/utils.py @@ -195,15 +195,6 @@ def _rename_server_farm_props(webapp): return webapp -def get_raw_functionapp(cmd, resource_group_name, name): - site_url_base = '/subscriptions/{}/resourceGroups/{}/providers/Microsoft.Web/sites/{}?api-version={}' - subscription_id = get_subscription_id(cmd.cli_ctx) - site_url = site_url_base.format(subscription_id, resource_group_name, name, '2023-12-01') - request_url = cmd.cli_ctx.cloud.endpoints.resource_manager + site_url - response = send_raw_request(cmd.cli_ctx, "GET", request_url) - return response.json() - - def _get_location_from_webapp(client, resource_group_name, webapp): webapp = client.web_apps.get(resource_group_name, webapp) if not webapp: From 782cebbd399afdbdc58d166ea1735e013d9e02f6 Mon Sep 17 00:00:00 2001 From: Kirstyn Joy Amperiadis Date: Fri, 23 Feb 2024 15:40:37 -0600 Subject: [PATCH 4/5] Update to new API version --- src/azure-cli-core/azure/cli/core/profiles/_shared.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/azure-cli-core/azure/cli/core/profiles/_shared.py b/src/azure-cli-core/azure/cli/core/profiles/_shared.py index 120065f0e6c..30ba981d858 100644 --- a/src/azure-cli-core/azure/cli/core/profiles/_shared.py +++ b/src/azure-cli-core/azure/cli/core/profiles/_shared.py @@ -254,7 +254,7 @@ def default_api_version(self): 'subscription_diagnostic_settings': '2017-05-01-preview' }), ResourceType.MGMT_MSI: '2023-01-31', - ResourceType.MGMT_APPSERVICE: '2023-01-01', + ResourceType.MGMT_APPSERVICE: '2023-12-01', ResourceType.MGMT_IOTHUB: '2023-06-30-preview', ResourceType.MGMT_IOTDPS: '2021-10-15', ResourceType.MGMT_IOTCENTRAL: '2021-11-01-preview', From d1e901283d529faee2287018b43b76e3c10d3233 Mon Sep 17 00:00:00 2001 From: Azure CLI Team Date: Sun, 25 Feb 2024 18:05:34 +0000 Subject: [PATCH 5/5] Rerun tests from instance 6. See test_results_None_latest_6.parallel.xml for details --- .../latest/test_marketplaceordering_scenario_coverage.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/marketplaceordering/tests/latest/test_marketplaceordering_scenario_coverage.md b/src/azure-cli/azure/cli/command_modules/marketplaceordering/tests/latest/test_marketplaceordering_scenario_coverage.md index b719157373e..a8527cb3130 100644 --- a/src/azure-cli/azure/cli/command_modules/marketplaceordering/tests/latest/test_marketplaceordering_scenario_coverage.md +++ b/src/azure-cli/azure/cli/command_modules/marketplaceordering/tests/latest/test_marketplaceordering_scenario_coverage.md @@ -1,4 +1,4 @@ |Scenario|Result|ErrorMessage|ErrorStack|ErrorNormalized|StartDt|EndDt| -|step_accept|successed||||2023-12-04 18:34:23.522863|2023-12-04 18:34:23.939434| -|step_show|successed||||2023-12-04 18:34:23.984279|2023-12-04 18:34:24.206306| +|step_accept|successed||||2024-02-25 18:05:27.572439|2024-02-25 18:05:27.692386| +|step_show|successed||||2024-02-25 18:05:27.692563|2024-02-25 18:05:27.701586| Coverage: 2/2