Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/spring-cloud/HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
Release History
===============

2.6.0
-----
* Add support for 0.5 core, 512 Mi resource requests in app deployment

2.5.1
-----
* Revert `2.5.0` as a quick fix for incompatibility with old api-version.
* Revert `2.5.0` as a quick fix for incompatibility with old api-version.

~~2.5.0~~
-----
Expand Down
107 changes: 58 additions & 49 deletions src/spring-cloud/azext_spring_cloud/_client_factory.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,58 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
from azure.cli.core.commands.client_factory import get_mgmt_service_client
from azure.cli.core.profiles import ResourceType
from .vendored_sdks.appplatform.v2020_07_01 import AppPlatformManagementClient
from .vendored_sdks.appplatform.v2020_11_01_preview import AppPlatformManagementClient as AppPlatformManagementClient_20201101preview


def cf_spring_cloud(cli_ctx, *_):
return get_mgmt_service_client(cli_ctx, AppPlatformManagementClient)


def cf_spring_cloud_20201101preview(cli_ctx, *_):
return get_mgmt_service_client(cli_ctx, AppPlatformManagementClient_20201101preview)


def cf_resource_groups(cli_ctx, subscription_id=None):
return get_mgmt_service_client(cli_ctx, ResourceType.MGMT_RESOURCE_RESOURCES,
subscription_id=subscription_id).resource_groups


def cf_app_services(cli_ctx, *_):
return cf_spring_cloud(cli_ctx).services


def cf_apps(cli_ctx, *_):
return cf_spring_cloud(cli_ctx).apps


def cf_deployments(cli_ctx, *_):
return cf_spring_cloud(cli_ctx).deployments


def cf_bindings(cli_ctx, *_):
return cf_spring_cloud(cli_ctx).bindings


def cf_config_servers(cli_ctx, *_):
return cf_spring_cloud(cli_ctx).config_servers


def cf_certificates(cli_ctx, *_):
return cf_spring_cloud(cli_ctx).certificates


def cf_custom_domains(cli_ctx, *_):
return cf_spring_cloud(cli_ctx).custom_domains
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
from azure.cli.core.commands.client_factory import get_mgmt_service_client
from azure.cli.core.profiles import ResourceType
from .vendored_sdks.appplatform.v2020_07_01 import AppPlatformManagementClient
from .vendored_sdks.appplatform.v2020_11_01_preview import (
AppPlatformManagementClient as AppPlatformManagementClient_20201101preview
)
from .vendored_sdks.appplatform.v2021_06_01_preview import (
AppPlatformManagementClient as AppPlatformManagementClient_20210601preview
)


def cf_spring_cloud(cli_ctx, *_):
return get_mgmt_service_client(cli_ctx, AppPlatformManagementClient)


def cf_spring_cloud_20201101preview(cli_ctx, *_):
return get_mgmt_service_client(cli_ctx, AppPlatformManagementClient_20201101preview)


def cf_spring_cloud_20210601preview(cli_ctx, *_):
return get_mgmt_service_client(cli_ctx, AppPlatformManagementClient_20210601preview)


def cf_resource_groups(cli_ctx, subscription_id=None):
return get_mgmt_service_client(cli_ctx, ResourceType.MGMT_RESOURCE_RESOURCES,
subscription_id=subscription_id).resource_groups


def cf_app_services(cli_ctx, *_):
return cf_spring_cloud(cli_ctx).services


def cf_apps(cli_ctx, *_):
return cf_spring_cloud(cli_ctx).apps


def cf_deployments(cli_ctx, *_):
return cf_spring_cloud(cli_ctx).deployments


def cf_bindings(cli_ctx, *_):
return cf_spring_cloud(cli_ctx).bindings


def cf_config_servers(cli_ctx, *_):
return cf_spring_cloud(cli_ctx).config_servers


def cf_certificates(cli_ctx, *_):
return cf_spring_cloud(cli_ctx).certificates


def cf_custom_domains(cli_ctx, *_):
return cf_spring_cloud(cli_ctx).custom_domains
16 changes: 8 additions & 8 deletions src/spring-cloud/azext_spring_cloud/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,10 @@ def load_arguments(self, _):
options_list=['--assign-endpoint', c.deprecate(target='--is-public', redirect='--assign-endpoint', hide=True)])
c.argument('assign_identity', arg_type=get_three_state_flag(),
help='If true, assign managed service identity.')
c.argument('cpu', type=int, default=1,
help='Number of virtual cpu cores per instance.')
c.argument('memory', type=int, default=1,
help='Number of GB of memory per instance.')
c.argument('cpu', type=str, default="1",
help='CPU resource quantity. Should be 500m or number of CPU cores.')
c.argument('memory', type=str, default="1Gi",
help='Memory resource quantity. Should be 512Mi or #Gi, e.g., 1Gi, 3Gi.')
Comment thread
zhoxing-ms marked this conversation as resolved.
c.argument('instance_count', type=int,
default=1, help='Number of instance.', validator=validate_instance_count)

Expand Down Expand Up @@ -140,8 +140,8 @@ def prepare_logs_argument(c):
c.argument('env', env_type)

with self.argument_context('spring-cloud app scale') as c:
c.argument('cpu', type=int, help='Number of virtual cpu cores per instance.')
c.argument('memory', type=int, help='Number of GB of memory per instance.')
c.argument('cpu', type=str, help='CPU resource quantity. Should be 500m or number of CPU cores.')
c.argument('memory', type=str, help='Memory resource quantity. Should be 512Mi or #Gi, e.g., 1Gi, 3Gi.')
Comment thread
zhoxing-ms marked this conversation as resolved.
c.argument('instance_count', type=int, help='Number of instance.', validator=validate_instance_count)

for scope in ['spring-cloud app deploy', 'spring-cloud app deployment create']:
Expand All @@ -160,8 +160,8 @@ def prepare_logs_argument(c):
with self.argument_context('spring-cloud app deployment create') as c:
c.argument('skip_clone_settings', help='Create staging deployment will automatically copy settings from production deployment.',
action='store_true')
c.argument('cpu', type=int, help='Number of virtual cpu cores per instance.')
c.argument('memory', type=int, help='Number of GB of memory per instance.')
c.argument('cpu', type=str, help='CPU resource quantity. Should be 500m or number of CPU cores.')
c.argument('memory', type=str, help='Memory resource quantity. Should be 512Mi or #Gi, e.g., 1Gi, 3Gi.')
Comment thread
zhoxing-ms marked this conversation as resolved.
c.argument('instance_count', type=int, help='Number of instance.', validator=validate_instance_count)

with self.argument_context('spring-cloud app deployment') as c:
Expand Down
54 changes: 54 additions & 0 deletions src/spring-cloud/azext_spring_cloud/_resource_quantity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------


import re
from knack.log import get_logger
from azure.cli.core.azclierror import InvalidArgumentValueError


logger = get_logger(__name__)


def validate_cpu(cpu):
'''
CPU quantity should be either integer, or millis. Currently, 500m (aka 0.5) is the only allowed fractional value.
Note that 1 can be represented as 1000m.
'''
if cpu is None:
return None

# some digit(s) followed by an optional m
if not re.match(r"^\d+m?$", cpu):
raise InvalidArgumentValueError("CPU quantity should be millis (500m) or integer (1, 2, ...)")

return cpu


def validate_memory(memory):
'''
Memory quantity should be in gigabytes (Gi) or megabytes (Mi). Currently, the only allowed fractional gigabytes
quantity is 512Mi. Note that 1Gi can be specified with 1024Mi.

In the legacy extension, gigabytes is specified with integer. This will generate a warning now.
'''
if memory is None:
return None

unified = memory
try:
# For backward compatibility, convert integer value to value with Gi unit
int(memory)
logger.warning("Memory quantity [--memory] should be specified with unit, such as 512Mi, 1Gi. "
"Support for integer quantity will be dropped in future release.")
unified = memory + "Gi"
except ValueError:
pass

# Some digit(s) followed by explicit unit (Mi or Gi)
if not re.match(r"^\d+[MG]i$", unified):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add some explanation for the function of the regular expression?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We allow the user to specify the memory quantity with either ###Mi or ###Gi, for example, 1024Mi, 3Gi. The code above this line is to add backward compatibility for legacy input, which uses integer for Gi values.

The regular expression here add some client side validation for the user input, to restrict it to be some digits followed by Mi or Gi. (Note that integer input will be converted to ###Gi before this validation).

raise InvalidArgumentValueError("Memory quantity should be integer followed by unit (Mi/Gi)")

return unified
11 changes: 8 additions & 3 deletions src/spring-cloud/azext_spring_cloud/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
# --------------------------------------------------------------------------------------------

# pylint: disable=line-too-long
from ._client_factory import (cf_app_services, cf_spring_cloud, cf_spring_cloud_20201101preview, cf_bindings, cf_config_servers)
from ._client_factory import (cf_app_services,
cf_spring_cloud,
cf_spring_cloud_20201101preview,
cf_spring_cloud_20210601preview,
cf_bindings,
cf_config_servers)
from ._transformers import (transform_spring_cloud_table_output,
transform_app_table_output,
transform_spring_cloud_deployment_output,
Expand Down Expand Up @@ -40,7 +45,7 @@ def load_command_table(self, _):
g.custom_command('repo update', 'config_repo_update')
g.custom_command('repo list', 'config_repo_list')

with self.command_group('spring-cloud app', client_factory=cf_spring_cloud_20201101preview) as g:
with self.command_group('spring-cloud app', client_factory=cf_spring_cloud_20210601preview) as g:
g.custom_command('create', 'app_create')
g.custom_command('update', 'app_update')
g.custom_command('deploy', 'app_deploy', supports_no_wait=True)
Expand Down Expand Up @@ -69,7 +74,7 @@ def load_command_table(self, _):
deprecate_info=g.deprecate(redirect='az spring-cloud app logs', hide=True)) as g:
g.custom_command('tail', 'app_tail_log')

with self.command_group('spring-cloud app deployment', client_factory=cf_spring_cloud) as g:
with self.command_group('spring-cloud app deployment', client_factory=cf_spring_cloud_20210601preview) as g:
g.custom_command('create', 'deployment_create', supports_no_wait=True)
g.custom_command('list', 'deployment_list',
table_transformer=transform_spring_cloud_deployment_output)
Expand Down
Loading