diff --git a/src/spring-cloud/azext_spring_cloud/_help.py b/src/spring-cloud/azext_spring_cloud/_help.py index a2a79194270..ee8e057f877 100644 --- a/src/spring-cloud/azext_spring_cloud/_help.py +++ b/src/spring-cloud/azext_spring_cloud/_help.py @@ -581,3 +581,29 @@ - name: Disable Application Insights. text: az spring-cloud app-insights update -n MyService -g MyResourceGroup --disable """ + +helps['spring-cloud service-registry'] = """ + type: group + short-summary: (Support Enterprise Tier Only) Commands to manage Service Registry in Azure Spring Cloud. +""" + +helps['spring-cloud service-registry show'] = """ + type: command + short-summary: Show the provisioning status and runtime status of Service Registry. +""" + +helps['spring-cloud service-registry bind'] = """ + type: command + short-summary: Bind an app to Service Registry. + examples: + - name: Bind an app to Service Registry. + text: az spring-cloud service-registry bind --app MyApp -s MyService -g MyResourceGroup +""" + +helps['spring-cloud service-registry unbind'] = """ + type: command + short-summary: Unbind an app from Service Registry. + examples: + - name: Unbind an app from Service Registry. + text: az spring-cloud service-registry unbind --app MyApp -s MyService -g MyResourceGroup +""" diff --git a/src/spring-cloud/azext_spring_cloud/_params.py b/src/spring-cloud/azext_spring_cloud/_params.py index 07bb44896fa..c7b21564ff4 100644 --- a/src/spring-cloud/azext_spring_cloud/_params.py +++ b/src/spring-cloud/azext_spring_cloud/_params.py @@ -14,6 +14,7 @@ validate_tracing_parameters_asc_create, validate_tracing_parameters_asc_update, validate_app_insights_parameters, validate_instance_count, validate_java_agent_parameters, validate_jar) +from ._validators_enterprise import only_support_enterprise from ._app_validator import (fulfill_deployment_param, active_deployment_exist, active_deployment_exist_under_app, ensure_not_active_deployment, validate_deloy_path, validate_deloyment_create_path, validate_cpu, validate_memory) @@ -410,3 +411,13 @@ def prepare_logs_argument(c): arg_type=get_three_state_flag(), help="Disable Application Insights.", validator=validate_app_insights_parameters) + + for scope in ['spring-cloud service-registry']: + with self.argument_context(scope) as c: + c.argument('service', service_name_type, validator=only_support_enterprise) + + with self.argument_context('spring-cloud service-registry bind') as c: + c.argument('app', app_name_type, help='Name of app.', validator=validate_app_name) + + with self.argument_context('spring-cloud service-registry unbind') as c: + c.argument('app', app_name_type, help='Name of app.', validator=validate_app_name) diff --git a/src/spring-cloud/azext_spring_cloud/_transformers.py b/src/spring-cloud/azext_spring_cloud/_transformers.py index adea6584fc9..b71339d8487 100644 --- a/src/spring-cloud/azext_spring_cloud/_transformers.py +++ b/src/spring-cloud/azext_spring_cloud/_transformers.py @@ -130,3 +130,26 @@ def _apply_deployment_table(item, deployment): item['Memory'] = deployment['properties']['deploymentSettings']['resourceRequests']['memory'] item['Running Instance'] = "{}/{}".format(running_number, instance_count) if isStarted else "Stopped" item['Registered Instance'] = _get_registration_state(deployment) + + +def transform_service_registry_output(result): + return _transform_tanzu_component_output(result) + + +def _transform_tanzu_component_output(result): + is_list = isinstance(result, list) + + if not is_list: + result = [result] + + for item in result: + instance_count = item['properties']['resourceRequests']['instanceCount'] + instances = item['properties']['instances'] or [] + running_number = len( + [x for x in instances if x['status'].upper() == "RUNNING"]) + item['Provisioning State'] = item['properties']['provisioningState'] + item['Running Instance'] = "{}/{}".format(running_number, instance_count) + item['CPU'] = item['properties']['resourceRequests']['cpu'] + item['Memory'] = item['properties']['resourceRequests']['memory'] + + return result if is_list else result[0] diff --git a/src/spring-cloud/azext_spring_cloud/_validators_enterprise.py b/src/spring-cloud/azext_spring_cloud/_validators_enterprise.py new file mode 100644 index 00000000000..b7d37af2b6b --- /dev/null +++ b/src/spring-cloud/azext_spring_cloud/_validators_enterprise.py @@ -0,0 +1,19 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- + +# pylint: disable=too-few-public-methods, unused-argument, redefined-builtin + +from azure.cli.core.azclierror import ClientRequestError +from ._util_enterprise import is_enterprise_tier + + +def only_support_enterprise(cmd, namespace): + if namespace.resource_group and namespace.service and not is_enterprise_tier(cmd, namespace.resource_group, namespace.service): + raise ClientRequestError("'{}' only supports for Enterprise tier Spring instance.".format(namespace.command)) + + +def not_support_enterprise(cmd, namespace): + if namespace.resource_group and namespace.service and is_enterprise_tier(cmd, namespace.resource_group, namespace.service): + raise ClientRequestError("'{}' doesn't support for Enterprise tier Spring instance.".format(namespace.command)) diff --git a/src/spring-cloud/azext_spring_cloud/commands.py b/src/spring-cloud/azext_spring_cloud/commands.py index 2279d7015eb..fd1542427e9 100644 --- a/src/spring-cloud/azext_spring_cloud/commands.py +++ b/src/spring-cloud/azext_spring_cloud/commands.py @@ -14,7 +14,8 @@ transform_app_table_output, transform_spring_cloud_deployment_output, transform_spring_cloud_certificate_output, - transform_spring_cloud_custom_domain_output) + transform_spring_cloud_custom_domain_output, + transform_service_registry_output) # pylint: disable=too-many-statements @@ -29,6 +30,11 @@ def load_command_table(self, _): client_factory=cf_spring_cloud_20220101preview ) + service_registry_cmd_group = CliCommandType( + operations_tmpl='azext_spring_cloud.service_registry#{}', + client_factory=cf_spring_cloud_20220101preview + ) + with self.command_group('spring-cloud', custom_command_type=spring_cloud_routing_util, exception_handler=handle_asc_exception) as g: g.custom_command('create', 'spring_cloud_create', supports_no_wait=True) @@ -158,5 +164,13 @@ def load_command_table(self, _): g.custom_command('update', 'app_insights_update', supports_no_wait=True) g.custom_show_command('show', 'app_insights_show') + with self.command_group('spring-cloud service-registry', + custom_command_type=service_registry_cmd_group, + exception_handler=handle_asc_exception, + is_preview=True) as g: + g.custom_show_command('show', 'service_registry_show', table_transformer=transform_service_registry_output) + g.custom_command('bind', 'service_registry_bind') + g.custom_command('unbind', 'service_registry_unbind') + with self.command_group('spring-cloud', exception_handler=handle_asc_exception): pass diff --git a/src/spring-cloud/azext_spring_cloud/service_registry.py b/src/spring-cloud/azext_spring_cloud/service_registry.py new file mode 100644 index 00000000000..84b898d1de8 --- /dev/null +++ b/src/spring-cloud/azext_spring_cloud/service_registry.py @@ -0,0 +1,64 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- + +# pylint: disable=unused-argument, logging-format-interpolation, protected-access, wrong-import-order, too-many-lines +from azure.cli.core.commands.client_factory import get_subscription_id +from knack.log import get_logger +from msrestazure.tools import resource_id + +SERVICE_REGISTRY_NAME = "serviceRegistry" +RESOURCE_ID = "resourceId" + +RESOURCE_TYPE = "serviceRegistries" +DEFAULT_NAME = "default" + +logger = get_logger(__name__) + + +def service_registry_show(cmd, client, service, resource_group): + return client.service_registries.get(resource_group, service, DEFAULT_NAME) + + +def service_registry_bind(cmd, client, service, resource_group, app): + return _service_registry_bind_or_unbind_app(cmd, client, service, resource_group, app, True) + + +def service_registry_unbind(cmd, client, service, resource_group, app): + return _service_registry_bind_or_unbind_app(cmd, client, service, resource_group, app, False) + + +def _service_registry_bind_or_unbind_app(cmd, client, service, resource_group, app_name, enabled): + app = client.apps.get(resource_group, service, app_name) + app.properties.addon_configs = _get_app_addon_configs_with_service_registry(app.properties.addon_configs) + + if (app.properties.addon_configs[SERVICE_REGISTRY_NAME][RESOURCE_ID] != "") == enabled: + logger.warning('App "{}" has been {}binded'.format(app_name, '' if enabled else 'un')) + return app + + service_registry_id = resource_id( + subscription=get_subscription_id(cmd.cli_ctx), + resource_group=resource_group, + namespace='Microsoft.AppPlatform', + type='Spring', + name=service, + child_type_1=RESOURCE_TYPE, + child_name_1=DEFAULT_NAME + ) + + if enabled: + app.properties.addon_configs[SERVICE_REGISTRY_NAME][RESOURCE_ID] = service_registry_id + else: + app.properties.addon_configs[SERVICE_REGISTRY_NAME][RESOURCE_ID] = "" + return client.apps.begin_update(resource_group, service, app_name, app) + + +def _get_app_addon_configs_with_service_registry(addon_configs): + if addon_configs is None: + addon_configs = {} + if addon_configs.get(SERVICE_REGISTRY_NAME) is None: + addon_configs[SERVICE_REGISTRY_NAME] = {} + if addon_configs[SERVICE_REGISTRY_NAME].get(RESOURCE_ID) is None: + addon_configs[SERVICE_REGISTRY_NAME][RESOURCE_ID] = "" + return addon_configs