Skip to content

Commit

Permalink
[Spring]validate path exist before all steps (#7725)
Browse files Browse the repository at this point in the history
  • Loading branch information
Netyyyy committed Jul 2, 2024
1 parent 9935e28 commit 35aeac7
Show file tree
Hide file tree
Showing 12 changed files with 1,746 additions and 5 deletions.
4 changes: 4 additions & 0 deletions src/spring/HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
Release History
===============
1.24.5
---
* Verify that `--artifact-path` and `--source-path` exist before all steps in `az spring app deploy`, `az spring app deployment create` and `az spring job deploy` commands.

1.24.4
---
* Refine the error message when user failed to get job log streaming in command `az spring job logs`.
Expand Down
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.'.format(source_path))
if artifact_path and not os.path.exists(artifact_path):
raise InvalidArgumentValueError('artifact path {} does not exist.'.format(artifact_path))
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":"9b9e547a4196418d96427d7fe1421e91","networkProfile":{"outboundIPs":{"publicIPs":["20.162.177.38","20.254.82.240"]},"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-19T04:54:54.0896323Z","lastModifiedBy":"[email protected]","lastModifiedByType":"User","lastModifiedAt":"2024-06-19T04:54:54.0896323Z"}}'
headers:
cache-control:
- no-cache
content-length:
- '947'
content-type:
- application/json
date:
- Wed, 19 Jun 2024 05:01:38 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:
- '11999'
x-msedge-ref:
- 'Ref A: 4CA6CB34EF2D4906A7F467EED45E16F4 Ref B: TYO201151006034 Ref C: 2024-06-19T05:01:37Z'
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/myjob?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/myjob","details":null}}'
headers:
cache-control:
- no-cache
content-length:
- '230'
content-type:
- application/json
date:
- Wed, 19 Jun 2024 05:01: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-msedge-ref:
- 'Ref A: 58002E6001B742868F4DD3B1F661E7BA Ref B: TYO201151004034 Ref C: 2024-06-19T05:01:39Z'
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/myjob?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/myjob","name":"myjob","systemData":{"createdBy":"[email protected]","createdByType":"User","createdAt":"2024-06-19T05:01:42.0072873Z","lastModifiedBy":"[email protected]","lastModifiedByType":"User","lastModifiedAt":"2024-06-19T05:01:42.0072873Z"}}'
headers:
cache-control:
- no-cache
content-length:
- '661'
content-type:
- application/json
date:
- Wed, 19 Jun 2024 05:01:43 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: 7DE6AE5D3AED45DB9D3EBB3A8D500705 Ref B: TYO201100115025 Ref C: 2024-06-19T05:01:41Z'
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/myjob?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/myjob","name":"myjob","systemData":{"createdBy":"[email protected]","createdByType":"User","createdAt":"2024-06-19T05:01:42.0072873Z","lastModifiedBy":"[email protected]","lastModifiedByType":"User","lastModifiedAt":"2024-06-19T05:01:42.0072873Z"}}'
headers:
cache-control:
- no-cache
content-length:
- '661'
content-type:
- application/json
date:
- Wed, 19 Jun 2024 05:01:45 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: 8121A5E1437D4652AAB3271D1AB24773 Ref B: TYO201151005060 Ref C: 2024-06-19T05:01:44Z'
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': 'myjob',
'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.".format(file_path)):
self.cmd('spring job deploy -n {job} -g {rg} -s {serviceName} --artifact-path {file}')
Loading

0 comments on commit 35aeac7

Please sign in to comment.