Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
61 changes: 61 additions & 0 deletions src/spring-cloud/azext_spring_cloud/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -846,3 +846,64 @@
type: command
short-summary: Unbind a custom-domain of the API portal.
"""

helps['spring-cloud build-service'] = """
type: group
short-summary: (Support Enterprise Tier Only) Commands to manage build service in Azure Spring Cloud.
"""

helps['spring-cloud build-service builder'] = """
type: group
short-summary: (Support Enterprise Tier Only) Commands to manage builder of build service.
"""

helps['spring-cloud build-service builder buildpack-binding'] = """
type: group
short-summary: (Support Enterprise Tier Only) Commands to manage buildpack-binding of builder.
"""

helps['spring-cloud build-service builder buildpack-binding create'] = """
type: command
short-summary: (Support Enterprise Tier Only) Create a buildpack binding.
examples:
- name: Create a buildpack binding without properties or secrets.
text: az spring-cloud build-service builder buildpack-binding create --name first-binding --builder-name first-builder --type ApplicationInsights --service MyCluster --resource-group MyResourceGroup
- name: Create a buildpack binding with only secrets.
text: az spring-cloud build-service builder buildpack-binding create --name first-binding --builder-name first-builder --type ApplicationInsights --secrets k1=v1 k2=v2 --service MyCluster --resource-group MyResourceGroup
- name: Create a buildpack binding with only properties.
text: az spring-cloud build-service builder buildpack-binding create --name first-binding --builder-name first-builder --type ApplicationInsights --properties a=b c=d --service MyCluster --resource-group MyResourceGroup
- name: Create a buildpack binding with properties and secrets.
text: az spring-cloud build-service builder buildpack-binding create --name first-binding --builder-name first-builder --type ApplicationInsights --properties a=b c=d --secrets k1=v1 k2=v2 --service MyCluster --resource-group MyResourceGroup
"""

helps['spring-cloud build-service builder buildpack-binding set'] = """
type: command
short-summary: (Support Enterprise Tier Only) Set a buildpack binding.
examples:
- name: Set a buildpack binding with properties and secrets.
text: az spring-cloud build-service builder buildpack-binding set --name first-binding --builder-name first-builder --type ApplicationInsights --properties a=b c=d --secrets k1=v1 k2=v2 --service MyCluster --resource-group MyResourceGroup
"""

helps['spring-cloud build-service builder buildpack-binding show'] = """
type: command
short-summary: (Support Enterprise Tier Only) Show a buildpack binding. The secrets will be masked.
examples:
- name: Show a buildpack binding.
text: az spring-cloud build-service builder buildpack-binding show --name first-binding --builder-name first-builder --service MyCluster --resource-group MyResourceGroup
"""

helps['spring-cloud build-service builder buildpack-binding list'] = """
type: command
short-summary: (Support Enterprise Tier Only) List all buildpack binding in a builder. The secrets will be masked.
examples:
- name: Show a buildpack binding.
text: az spring-cloud build-service builder buildpack-binding list --builder-name first-builder --service MyCluster --resource-group MyResourceGroup
"""
Comment on lines +895 to +901

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.

name: Show a buildpack binding.

Why is the description here Show rather than list?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch, thank you!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated.


helps['spring-cloud build-service builder buildpack-binding delete'] = """
type: command
short-summary: (Support Enterprise Tier Only) Delete a buildpack binding.
examples:
- name: Delete a buildpack binding.
text: az spring-cloud build-service builder buildpack-binding delete --name first-binding --builder-name first-builder --service MyCluster --resource-group MyResourceGroup
"""
66 changes: 63 additions & 3 deletions src/spring-cloud/azext_spring_cloud/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@
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,
validate_git_uri, validate_acs_patterns,
validate_routes)
from ._validators_enterprise import (only_support_enterprise, validate_git_uri, validate_acs_patterns, validate_routes,
validate_buildpack_binding_exist, validate_buildpack_binding_not_exist,
validate_buildpack_binding_properties, validate_buildpack_binding_secrets)
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)
from ._utils import ApiType

from .vendored_sdks.appplatform.v2020_07_01.models import RuntimeVersion, TestKeyType
from .vendored_sdks.appplatform.v2022_01_01_preview.models \
import _app_platform_management_client_enums as v20220101_preview_AppPlatformEnums

name_type = CLIArgumentType(options_list=[
'--name', '-n'], help='The primary resource name', validator=validate_name)
Expand Down Expand Up @@ -424,6 +426,12 @@ def prepare_logs_argument(c):
with self.argument_context('spring-cloud {}'.format(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)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Duplicate with line 437, please delete line 429-433


for scope in ['bind', 'unbind']:
with self.argument_context('spring-cloud service-registry {}'.format(scope)) as c:
c.argument('app', app_name_type, help='Name of app.', validator=validate_app_name)
Expand Down Expand Up @@ -500,3 +508,55 @@ def prepare_logs_argument(c):
c.argument('app_name', type=str, help="The Azure Spring Cloud app name to configure the route.")
c.argument('routes_json', type=str, help="The JSON array of API routes.", validator=validate_routes)
c.argument('routes_file', type=str, help="The file path of JSON array of API routes.", validator=validate_routes)

for scope in ['spring-cloud build-service builder buildpack-binding create']:
with self.argument_context(scope) as c:
c.argument('type',
arg_type=get_enum_type(v20220101_preview_AppPlatformEnums.BindingType),
help='Required type for buildpack binding.')
c.argument('properties',
help='Non-sensitive properties for launchProperties. Format "key[=value]".',
nargs='*',
validator=validate_buildpack_binding_properties)
c.argument('secrets',
help='Sensitive properties for launchProperties. '
'Once put, it will be encrypted and never return to user. '
'Format "key[=value]".',
nargs='*',
validator=validate_buildpack_binding_secrets)
c.argument('name', help='Name for buildpack binding.', validator=validate_buildpack_binding_not_exist)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
c.argument('name', help='Name for buildpack binding.', validator=validate_buildpack_binding_not_exist)
c.argument('name', name_type, help='Name for buildpack binding.', validator=validate_buildpack_binding_not_exist)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated.

c.argument('builder_name', help='The name for builder.', default="default")
c.argument('service', service_name_type, validator=only_support_enterprise)


for scope in ['spring-cloud build-service builder buildpack-binding set']:

@wangzelin007 wangzelin007 Jan 7, 2022

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's better to merge spring-cloud build-service builder buildpack-binding create with set except the argument name.
Otherwise we don't need to use scope here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

One question, is this the convention to merge such kinds of statements? If so, I can align this.
As a beginner to CLI, I intended to write parms like this, because it is clean when I look into one command for parameters. I can have a full picture of all parameters of one command.
Compare to merging, I may need to combine these in my mind for full picture.

Could you please help to enlighten me what is the best practice here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hi Li,
We highly recommend merging, because after merging, the similarities and differences can be more clearly distinguished.
If you modify it later,it is not easy to miss anything after merge.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

sure, updated.

with self.argument_context(scope) as c:
c.argument('type',
arg_type=get_enum_type(v20220101_preview_AppPlatformEnums.BindingType),
help='Required type for buildpack binding.')
c.argument('properties',
help='Non-sensitive properties for launchProperties. Format "key[=value]".',
nargs='*',
validator=validate_buildpack_binding_properties)
c.argument('secrets',
help='Sensitive properties for launchProperties. '
'Once put, it will be encrypted and never return to user. '
'Format "key[=value]".',
nargs='*',
validator=validate_buildpack_binding_secrets)
c.argument('name', help='Name for buildpack binding.', validator=validate_buildpack_binding_exist)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
c.argument('name', help='Name for buildpack binding.', validator=validate_buildpack_binding_exist)
c.argument('name', name_type, help='Name for buildpack binding.', validator=validate_buildpack_binding_exist)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated.

c.argument('builder_name', help='The name for builder.', default="default")
c.argument('service', service_name_type, validator=only_support_enterprise)


for scope in ['spring-cloud build-service builder buildpack-binding show',
'spring-cloud build-service builder buildpack-binding delete']:
with self.argument_context(scope) as c:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
with self.argument_context(scope) as c:
for scope in ['show', 'delete']:
with self.argument_context('spring-cloud build-service builder buildpack-binding {}'.format(scope)) as c:

c.argument('name', help='Name for buildpack binding.', validator=validate_buildpack_binding_exist)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
c.argument('name', help='Name for buildpack binding.', validator=validate_buildpack_binding_exist)
c.argument('name', name_type, help='Name for buildpack binding.', validator=validate_buildpack_binding_exist)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated.

c.argument('builder_name', help='The name for builder.', default="default")
c.argument('service', service_name_type, validator=only_support_enterprise)

for scope in ['spring-cloud build-service builder buildpack-binding list']:
with self.argument_context(scope) as c:
c.argument('builder_name', help='The name for builder.', default="default")
c.argument('service', service_name_type, validator=only_support_enterprise)
54 changes: 52 additions & 2 deletions src/spring-cloud/azext_spring_cloud/_validators_enterprise.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
# pylint: disable=too-few-public-methods, unused-argument, redefined-builtin

from re import match

from azure.cli.core.commands.validators import validate_tag
from azure.core.exceptions import ResourceNotFoundError
from azure.cli.core.util import CLIError

@zhoxing-ms zhoxing-ms Jan 10, 2022

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.

from azure.cli.core.util import CLIError

Please remove the useless import

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated.

from azure.cli.core.azclierror import (ArgumentUsageError, ClientRequestError,
InvalidArgumentValueError,
MutuallyExclusiveArgumentError)
Expand All @@ -15,8 +17,11 @@
from ._resource_quantity import validate_cpu as validate_and_normalize_cpu
from ._resource_quantity import \
validate_memory as validate_and_normalize_memory
from ._util_enterprise import is_enterprise_tier
from ._util_enterprise import (
is_enterprise_tier, get_client
)
from ._validators import validate_instance_count
from .buildpack_binding import (DEFAULT_BUILD_SERVICE_NAME)

logger = get_logger(__name__)

Expand Down Expand Up @@ -116,3 +121,48 @@ def validate_api_portal_instance_count(namespace):
if namespace.api_portal_instance_count is not None:
if namespace.api_portal_instance_count < 1:
raise InvalidArgumentValueError("--api-portal-instance-count must be greater than 0")


def validate_buildpack_binding_properties(namespace):
""" Extracts multiple space-separated properties in key[=value] format """
if isinstance(namespace.properties, list):
properties_dict = {}
for item in namespace.properties:
properties_dict.update(validate_tag(item))
namespace.properties = properties_dict


def validate_buildpack_binding_secrets(namespace):
""" Extracts multiple space-separated secrets in key[=value] format """
if isinstance(namespace.secrets, list):
secrets_dict = {}
for item in namespace.secrets:
secrets_dict.update(validate_tag(item))
namespace.secrets = secrets_dict


def validate_buildpack_binding_not_exist(cmd, namespace):
client = get_client(cmd)
try:
binding_resource = client.buildpack_binding.get(namespace.resource_group,
namespace.service,
DEFAULT_BUILD_SERVICE_NAME,
namespace.builder_name,
namespace.name)
if binding_resource is not None:
raise CLIError('buildpack Binding {} in builder {} already exists '

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you please use a specific error type instead of CLIError ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sure.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated.

'in resource group {}, service {}. You can edit it by set command.'
.format(namespace.name, namespace.resource_group, namespace.service, namespace.builder_name))
except ResourceNotFoundError:
# Excepted case
pass


def validate_buildpack_binding_exist(cmd, namespace):
client = get_client(cmd)
# If not exists exception will be raised
client.buildpack_binding.get(namespace.resource_group,
namespace.service,
DEFAULT_BUILD_SERVICE_NAME,
namespace.builder_name,
namespace.name)
Loading