Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Spring]validate path exist before all steps #7725

Merged
merged 11 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
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.
Netyyyy marked this conversation as resolved.
Show resolved Hide resolved

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.')
Netyyyy marked this conversation as resolved.
Show resolved Hide resolved
if artifact_path and not os.path.exists(artifact_path):
raise InvalidArgumentValueError('artifact path does not exist.')
Netyyyy marked this conversation as resolved.
Show resolved Hide resolved
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":"8d4afadc536241c398ed2002ea35289c","networkProfile":{"outboundIPs":{"publicIPs":["20.162.176.193","4.158.38.222"]},"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-19T02:34:24.2348658Z","lastModifiedBy":"[email protected]","lastModifiedByType":"User","lastModifiedAt":"2024-06-19T02:34:24.2348658Z"}}'
headers:
cache-control:
- no-cache
content-length:
- '947'
content-type:
- application/json
date:
- Wed, 19 Jun 2024 02:40:44 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: 43CD1A2F78C74292BF93E59889660351 Ref B: TYO201100113037 Ref C: 2024-06-19T02:40:43Z'
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 02:40: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: 22E1B558AB9C48F49AD48367F977FAF4 Ref B: TYO201100116039 Ref C: 2024-06-19T02:40:45Z'
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-19T02:40:48.2574098Z","lastModifiedBy":"[email protected]","lastModifiedByType":"User","lastModifiedAt":"2024-06-19T02:40:48.2574098Z"}}'
headers:
cache-control:
- no-cache
content-length:
- '661'
content-type:
- application/json
date:
- Wed, 19 Jun 2024 02:40:49 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:
- '1198'
x-msedge-ref:
- 'Ref A: C0766283383B4DE7AFA882271D40E615 Ref B: TYO201100114011 Ref C: 2024-06-19T02:40:47Z'
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-19T02:40:48.2574098Z","lastModifiedBy":"[email protected]","lastModifiedByType":"User","lastModifiedAt":"2024-06-19T02:40:48.2574098Z"}}'
headers:
cache-control:
- no-cache
content-length:
- '661'
content-type:
- application/json
date:
- Wed, 19 Jun 2024 02:40:51 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: 92F2E316BF284AE39A8E769014D7823D Ref B: TYO201100116025 Ref C: 2024-06-19T02:40:50Z'
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."):
self.cmd('spring job deploy -n {job} -g {rg} -s {serviceName} --artifact-path {file}')
Loading
Loading