Skip to content

Commit

Permalink
validate path before start create
Browse files Browse the repository at this point in the history
  • Loading branch information
Netyyyy committed Jun 18, 2024
1 parent f1c51a4 commit 75d8064
Show file tree
Hide file tree
Showing 9 changed files with 1,692 additions and 3 deletions.
10 changes: 10 additions & 0 deletions src/spring/azext_spring/_app_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# --------------------------------------------------------------------------------------------

# pylint: disable=too-few-public-methods, unused-argument, redefined-builtin
import os.path
from knack.log import get_logger
from azure.cli.core.azclierror import InvalidArgumentValueError
from msrestazure.azure_exceptions import CloudError
Expand Down Expand Up @@ -104,12 +105,14 @@ def validate_deloy_path(cmd, namespace):
arguments = [namespace.artifact_path, namespace.source_path, namespace.container_image]
if all(not x for x in arguments):
raise InvalidArgumentValueError('One of --artifact-path, --source-path, --container-image must be provided.')
validate_path_exist(namespace.source_path, namespace.artifact_path)
_deploy_path_mutual_exclusive(arguments)
_validate_container_registry(cmd, namespace)


def validate_deloyment_create_path(cmd, namespace):
arguments = [namespace.artifact_path, namespace.source_path, namespace.container_image]
validate_path_exist(namespace.source_path, namespace.artifact_path)
_deploy_path_mutual_exclusive(arguments)
_validate_container_registry(cmd, namespace)

Expand Down Expand Up @@ -162,3 +165,10 @@ def _validate_container_registry(cmd, namespace):
raise InvalidArgumentValueError(
"The instance without build service can only use '--container-image' to deploy."
" See more details in https://learn.microsoft.com/en-us/azure/spring-apps/how-to-deploy-with-custom-container-image?tabs=azure-cli")


def validate_path_exist(source_path, artifact_path):
if source_path and not os.path.exists(source_path):
raise InvalidArgumentValueError('source path does not exist.')
if artifact_path and not os.path.exists(artifact_path):
raise InvalidArgumentValueError('artifact path does not exist.')
6 changes: 3 additions & 3 deletions src/spring/azext_spring/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
validate_create_app_binding_default_service_registry)
from ._app_validator import (fulfill_deployment_param, active_deployment_exist,
ensure_not_active_deployment, validate_deloy_path, validate_deloyment_create_path,
validate_cpu, validate_build_cpu, validate_memory, validate_build_memory,
validate_cpu, validate_build_cpu, validate_memory, validate_build_memory, validate_path_exist,
fulfill_deployment_param_or_warning, active_deployment_exist_or_warning)
from .log_stream.log_stream_validators import (validate_log_lines, validate_log_limit, validate_log_since)
from ._app_managed_identity_validator import (validate_create_app_with_user_identity_or_warning,
Expand Down Expand Up @@ -1226,8 +1226,8 @@ def prepare_common_logs_argument(c):
c.argument('build_env', build_env_type)
c.argument('build_cpu', arg_type=build_cpu_type, default="1")
c.argument('build_memory', arg_type=build_memory_type, default="2Gi")
c.argument('source_path', arg_type=source_path_type)
c.argument('artifact_path', help='Deploy the specified pre-built artifact (jar or netcore zip).')
c.argument('source_path', arg_type=source_path_type, validator=validate_path_exist)
c.argument('artifact_path', help='Deploy the specified pre-built artifact (jar or netcore zip).', validator=validate_path_exist)
c.argument('disable_validation', arg_type=get_three_state_flag(), help='If true, disable jar validation.')

for scope in ['job create', 'job update', 'job deploy', 'job start']:
Expand Down
2 changes: 2 additions & 0 deletions src/spring/azext_spring/_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from ._util_enterprise import is_enterprise_tier
from .vendored_sdks.appplatform.v2024_05_01_preview import models
from ._constant import (MARKETPLACE_OFFER_ID, MARKETPLACE_PLAN_ID, MARKETPLACE_PUBLISHER_ID)
from ._app_validator import validate_path_exist

logger = get_logger(__name__)

Expand Down Expand Up @@ -578,6 +579,7 @@ def validate_jar(namespace):
if values is None:
# ignore jar_file check
return
validate_path_exist(namespace.source_path, namespace.artifact_path)

tips = ", if you choose to ignore these errors, turn validation off with --disable-validation"
if not values["has_jar"] and not values["has_class"]:
Expand Down
3 changes: 3 additions & 0 deletions src/spring/azext_spring/_validators_enterprise.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
)
from ._validators import (validate_instance_count, _parse_sku_name, _parse_jar_file)
from .buildpack_binding import (DEFAULT_BUILD_SERVICE_NAME)
from ._app_validator import validate_path_exist

logger = get_logger(__name__)

Expand Down Expand Up @@ -183,6 +184,7 @@ def validate_source_path(namespace):
valued_args = [x for x in arguments if x]
if len(valued_args) > 1:
raise InvalidArgumentValueError('At most one of --artifact-path, --source-path must be provided.')
validate_path_exist(namespace.source_path, namespace.artifact_path)


def validate_artifact_path(namespace):
Expand All @@ -195,6 +197,7 @@ def validate_artifact_path(namespace):
if values is None:
# ignore jar_file check
return
validate_path_exist(namespace.source_path, namespace.artifact_path)
file_size, spring_boot_version, spring_cloud_version, has_actuator, has_manifest, has_jar, has_class, ms_sdk_version, jdk_version = values

tips = ", if you choose to ignore these errors, turn validation off with --disable-validation"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
interactions:
- request:
body: null
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
CommandName:
- spring job create
Connection:
- keep-alive
ParameterSetName:
- -n -g -s
User-Agent:
- AZURECLI/2.61.0 azsdk-python-core/1.30.1 Python/3.11.9 (Windows-10-10.0.22631-SP0)
method: GET
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.AppPlatform/Spring/clitest000002?api-version=2024-05-01-preview
response:
body:
string: '{"properties":{"provisioningState":"Succeeded","zoneRedundant":false,"version":3,"serviceId":"f9520f7dba364c6f98a81e06d3306e4d","networkProfile":{"outboundIPs":{"publicIPs":["172.166.86.56","52.151.108.183"]},"outboundType":"loadBalancer"},"powerState":"Running","fqdn":"clitest000002.azuremicroservices.io","marketplaceResource":{"plan":"asa-ent-hr-mtr","publisher":"vmware-inc","product":"azure-spring-cloud-vmware-tanzu-2"}},"type":"Microsoft.AppPlatform/Spring","sku":{"name":"E0","tier":"Enterprise"},"location":"uksouth","tags":null,"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.AppPlatform/Spring/clitest000002","name":"clitest000002","systemData":{"createdBy":"[email protected]","createdByType":"User","createdAt":"2024-06-18T08:55:21.6646486Z","lastModifiedBy":"[email protected]","lastModifiedByType":"User","lastModifiedAt":"2024-06-18T08:55:21.6646486Z"}}'
headers:
cache-control:
- no-cache
content-length:
- '948'
content-type:
- application/json
date:
- Tue, 18 Jun 2024 09:02:35 GMT
expires:
- '-1'
pragma:
- no-cache
request-context:
- appId=cid-v1:797d7e4e-8180-497e-a254-780fbd39ba4d
strict-transport-security:
- max-age=31536000; includeSubDomains
x-cache:
- CONFIG_NOCACHE
x-content-type-options:
- nosniff
x-ms-ratelimit-remaining-subscription-resource-requests:
- '11998'
x-msedge-ref:
- 'Ref A: BF07FCC9F8FB486CA00CDF073D3F8B3F Ref B: MAA201060515011 Ref C: 2024-06-18T09:02:35Z'
x-rp-server-mvid:
- 16f8ed7c-99fe-42f5-98dc-7ba9e82d32d1
status:
code: 200
message: OK
- request:
body: null
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
CommandName:
- spring job create
Connection:
- keep-alive
ParameterSetName:
- -n -g -s
User-Agent:
- AZURECLI/2.61.0 azsdk-python-core/1.30.1 Python/3.11.9 (Windows-10-10.0.22631-SP0)
method: GET
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.AppPlatform/Spring/clitest000002/jobs/jobname?api-version=2024-05-01-preview
response:
body:
string: '{"error":{"code":"NotFound","message":"Job not found.","target":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.AppPlatform/Spring/clitest000002/jobs/jobname","details":null}}'
headers:
cache-control:
- no-cache
content-length:
- '232'
content-type:
- application/json
date:
- Tue, 18 Jun 2024 09:02:37 GMT
expires:
- '-1'
pragma:
- no-cache
request-context:
- appId=cid-v1:797d7e4e-8180-497e-a254-780fbd39ba4d
strict-transport-security:
- max-age=31536000; includeSubDomains
x-cache:
- CONFIG_NOCACHE
x-content-type-options:
- nosniff
x-msedge-ref:
- 'Ref A: CEF0EDE6D4894719AB3A48B6A4529BB1 Ref B: MAA201060513029 Ref C: 2024-06-18T09:02:37Z'
x-rp-server-mvid:
- 16f8ed7c-99fe-42f5-98dc-7ba9e82d32d1
status:
code: 404
message: Not Found
- request:
body: '{"properties": {"template": {"environmentVariables": [], "resourceRequests":
{"cpu": "1", "memory": "2Gi"}}, "managedComponentReferences": [], "triggerConfig":
{"triggerType": "Manual"}}}'
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
CommandName:
- spring job create
Connection:
- keep-alive
Content-Length:
- '187'
Content-Type:
- application/json
ParameterSetName:
- -n -g -s
User-Agent:
- AZURECLI/2.61.0 azsdk-python-core/1.30.1 Python/3.11.9 (Windows-10-10.0.22631-SP0)
method: PUT
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.AppPlatform/Spring/clitest000002/jobs/jobname?api-version=2024-05-01-preview
response:
body:
string: '{"properties":{"provisioningState":"Succeeded","triggerConfig":{"triggerType":"Manual"},"template":{"environmentVariables":[],"resourceRequests":{"cpu":"1","memory":"2Gi"}},"managedComponentReferences":[]},"type":"Microsoft.AppPlatform/Spring/jobs","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.AppPlatform/Spring/clitest000002/jobs/jobname","name":"jobname","systemData":{"createdBy":"[email protected]","createdByType":"User","createdAt":"2024-06-18T09:02:39.5631944Z","lastModifiedBy":"[email protected]","lastModifiedByType":"User","lastModifiedAt":"2024-06-18T09:02:39.5631944Z"}}'
headers:
cache-control:
- no-cache
content-length:
- '665'
content-type:
- application/json
date:
- Tue, 18 Jun 2024 09:02:40 GMT
expires:
- '-1'
pragma:
- no-cache
request-context:
- appId=cid-v1:797d7e4e-8180-497e-a254-780fbd39ba4d
strict-transport-security:
- max-age=31536000; includeSubDomains
x-cache:
- CONFIG_NOCACHE
x-content-type-options:
- nosniff
x-ms-ratelimit-remaining-subscription-writes:
- '1199'
x-msedge-ref:
- 'Ref A: 9B6C740EEC294DF4B10B81BECA99FE1D Ref B: MAA201060514019 Ref C: 2024-06-18T09:02:39Z'
x-rp-server-mvid:
- 16f8ed7c-99fe-42f5-98dc-7ba9e82d32d1
status:
code: 200
message: OK
- request:
body: null
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
CommandName:
- spring job create
Connection:
- keep-alive
ParameterSetName:
- -n -g -s
User-Agent:
- AZURECLI/2.61.0 azsdk-python-core/1.30.1 Python/3.11.9 (Windows-10-10.0.22631-SP0)
method: GET
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.AppPlatform/Spring/clitest000002/jobs/jobname?api-version=2024-05-01-preview
response:
body:
string: '{"properties":{"provisioningState":"Succeeded","triggerConfig":{"triggerType":"Manual"},"template":{"environmentVariables":[],"resourceRequests":{"cpu":"1","memory":"2Gi"}},"managedComponentReferences":[]},"type":"Microsoft.AppPlatform/Spring/jobs","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.AppPlatform/Spring/clitest000002/jobs/jobname","name":"jobname","systemData":{"createdBy":"[email protected]","createdByType":"User","createdAt":"2024-06-18T09:02:39.5631944Z","lastModifiedBy":"[email protected]","lastModifiedByType":"User","lastModifiedAt":"2024-06-18T09:02:39.5631944Z"}}'
headers:
cache-control:
- no-cache
content-length:
- '665'
content-type:
- application/json
date:
- Tue, 18 Jun 2024 09:02:42 GMT
expires:
- '-1'
pragma:
- no-cache
request-context:
- appId=cid-v1:797d7e4e-8180-497e-a254-780fbd39ba4d
strict-transport-security:
- max-age=31536000; includeSubDomains
x-cache:
- CONFIG_NOCACHE
x-content-type-options:
- nosniff
x-msedge-ref:
- 'Ref A: F42A0765A49A45938FEA4EF66AF3FE52 Ref B: MAA201060514023 Ref C: 2024-06-18T09:02:41Z'
x-rp-server-mvid:
- 16f8ed7c-99fe-42f5-98dc-7ba9e82d32d1
status:
code: 200
message: OK
version: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

import os

from knack.util import CLIError
from azure.cli.testsdk import (ScenarioTest, record_only)
from ..custom_preparers import (SpringPreparer, SpringResourceGroupPreparer)
from ..custom_dev_setting_constant import SpringTestEnvironmentEnum


class JobDeploy(ScenarioTest):

@SpringResourceGroupPreparer(dev_setting_name=SpringTestEnvironmentEnum.ENTERPRISE['resource_group_name'])
@SpringPreparer(**SpringTestEnvironmentEnum.ENTERPRISE['spring'])
def test_asa_job_deploy(self, resource_group, spring):
py_path = os.path.abspath(os.path.dirname(__file__))
file_path = os.path.join(py_path, 'files/test1.jar').replace("\\", "/")
self.kwargs.update({
'job': 'jobname',
'serviceName': spring,
'rg': resource_group,
'file': file_path
})

self.cmd('spring job create -n {job} -g {rg} -s {serviceName}', checks=[
self.check('name', '{job}')
])

# deploy unexist file, the fail is expected
with self.assertRaisesRegexp(CLIError, "artifact path does not exist."):
self.cmd('spring job deploy -n {job} -g {rg} -s {serviceName} --artifact-path {file}')
Loading

0 comments on commit 75d8064

Please sign in to comment.