Skip to content

Commit

Permalink
[Containerapp] az containerapp env java-component: Support Java compo…
Browse files Browse the repository at this point in the history
…nent (#7216)

* initial commit for Java components

* add JavaComponentPreviewClient in _clients.py

* add "az containerapp env java-component list"

* add show and delete command for Java component

* use different show and delete method for different java components

* refine show and delete logic

* add create and update command

* refine resource not found error

* refine model

* update client

* add configuration parameter

* fix patch command

* refine logic

* add bind

* fix bindname bug

* fix comments

* fix comments

* fix azdev linter error

* fix linter error

* fix comments

* fix comment

* fix comment

* add test for java component

* fix comment

* fix bug

* update test

* refine delete logic

* fix comment

* fix test error

* fix test issue

* fix test error

* fix test error

* fix test error

* fix test error

* fix comments

* fix comment

* fix test error test_containerapp_addon_binding_e2e

* fix test error - test_containerapp_dev_add_on_binding_customized_keys_e2e

* fix test error - test_containerapp_dev_add_on_binding_e2e

* fix test error - test_containerapp_dev_add_on_binding_none_client_type

* fix test error - test_containerapp_dev_service_binding_customized_keys_e2e

* fix test error - test_containerapp_dev_service_binding_customized_keys_yaml_e2e

* fix test error - test_containerapp_dev_service_binding_none_client_type

* fix test error - test_containerapp_managed_service_binding_e2e

* fix test error - test_containerapp_dev_add_on_binding_customized_keys_yaml_e2e

* fix test error - test_containerapp_dev_service_binding_e2e

* remove binding name validation

* update HISTORY.rst

* Revert "remove binding name validation"

This reverts commit c883393.

* add special logic to deal with java component binding name

* update unbind logic

* refine the model definition

* fix test - test_containerapp_java_component

* fix test error

* fix comments

* fix comment

* fix comment

* fix comment

* fix comment

* fix comment
  • Loading branch information
ShichaoQiu authored Feb 28, 2024
1 parent e6b430b commit 371ecd0
Show file tree
Hide file tree
Showing 22 changed files with 60,916 additions and 41,679 deletions.
4 changes: 4 additions & 0 deletions src/containerapp/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ upcoming
* 'az containerapp env dapr-component resiliency': Add support for Dapr Component Resiliency Circuit Breakers
* 'az containerapp create/update/up': Don't compress jar/war/zip file before upload source code
* 'az containerapp create/update/up': Update source to cloud builder to 20240124.1
* 'az containerapp env java-component': Support list Java components
* 'az containerapp env java-component spring-cloud-config': Support create/update/show/delete Spring Cloud Config
* 'az containerapp env java-component spring-cloud-eureka': Support create/update/show/delete Spring Cloud Eureka
* 'az containerapp create/update': Support bind Java component with --bind

0.3.47
++++++
Expand Down
2 changes: 1 addition & 1 deletion src/containerapp/azext_containerapp/_client_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def handle_non_404_exception(e):
def handle_non_404_status_code_exception(e):
import json

if hasattr(e, 'status_code') and e.status_code == 404:
if (hasattr(e, 'status_code') and e.status_code == 404) or (hasattr(e, 'response') and hasattr(e.response, 'status_code') and e.response.status_code == 404):
return e

string_err = str(e)
Expand Down
117 changes: 117 additions & 0 deletions src/containerapp/azext_containerapp/_clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -873,3 +873,120 @@ def list_auth_token(cls, cmd, builder_name, build_name, resource_group_name, loc
}
r = send_raw_request(cmd.cli_ctx, "POST", request_url, body=json.dumps(body_data))
return r.json()


class JavaComponentPreviewClient():
api_version = PREVIEW_API_VERSION

@classmethod
def create(cls, cmd, resource_group_name, environment_name, name, java_component_envelope, no_wait=False):
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
sub_id = get_subscription_id(cmd.cli_ctx)
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/managedEnvironments/{}/javaComponents/{}?api-version={}"
request_url = url_fmt.format(
management_hostname.strip('/'),
sub_id,
resource_group_name,
environment_name,
name,
cls.api_version)

r = send_raw_request(cmd.cli_ctx, "PUT", request_url, body=json.dumps(java_component_envelope))

if no_wait:
return r.json()
elif r.status_code == 201:
operation_url = r.headers.get(HEADER_AZURE_ASYNC_OPERATION)
poll_status(cmd, operation_url)
r = send_raw_request(cmd.cli_ctx, "GET", request_url)

return r.json()

@classmethod
def update(cls, cmd, resource_group_name, environment_name, name, java_component_envelope, no_wait=False):
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
sub_id = get_subscription_id(cmd.cli_ctx)
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/managedEnvironments/{}/javaComponents/{}?api-version={}"
request_url = url_fmt.format(
management_hostname.strip('/'),
sub_id,
resource_group_name,
environment_name,
name,
cls.api_version)

r = send_raw_request(cmd.cli_ctx, "PATCH", request_url, body=json.dumps(java_component_envelope))

if no_wait:
return
elif r.status_code == 202:
operation_url = r.headers.get(HEADER_LOCATION)
response = poll_results(cmd, operation_url)
if response is None:
raise ResourceNotFoundError("Could not find the Java component")
else:
return response

return r.json()

@classmethod
def delete(cls, cmd, resource_group_name, environment_name, name, no_wait=False):
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
sub_id = get_subscription_id(cmd.cli_ctx)
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/managedEnvironments/{}/javaComponents/{}?api-version={}"
request_url = url_fmt.format(
management_hostname.strip('/'),
sub_id,
resource_group_name,
environment_name,
name,
cls.api_version)

r = send_raw_request(cmd.cli_ctx, "DELETE", request_url)

if no_wait:
return # API doesn't return JSON (it returns no content)
elif r.status_code in [200, 201, 202, 204]:
if r.status_code == 202:
operation_url = r.headers.get(HEADER_LOCATION)
poll_results(cmd, operation_url)
logger.warning('Java component successfully deleted')

@classmethod
def show(cls, cmd, resource_group_name, environment_name, name):
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
sub_id = get_subscription_id(cmd.cli_ctx)
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/managedEnvironments/{}/javaComponents/{}?api-version={}"
request_url = url_fmt.format(
management_hostname.strip('/'),
sub_id,
resource_group_name,
environment_name,
name,
cls.api_version)

r = send_raw_request(cmd.cli_ctx, "GET", request_url)

return r.json()

@classmethod
def list(cls, cmd, resource_group_name, environment_name):
java_component_list = []

management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
sub_id = get_subscription_id(cmd.cli_ctx)
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/managedEnvironments/{}/javaComponents?api-version={}"
request_url = url_fmt.format(
management_hostname.strip('/'),
sub_id,
resource_group_name,
environment_name,
cls.api_version)

r = send_raw_request(cmd.cli_ctx, "GET", request_url)
r = r.json()

for component in r["value"]:
java_component_list.append(component)

return java_component_list
4 changes: 4 additions & 0 deletions src/containerapp/azext_containerapp/_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
CONNECTED_CLUSTER_TYPE = "connectedClusters"
AZURE_FILE_STORAGE_TYPE = "azureFile"
NFS_AZURE_FILE_STORAGE_TYPE = "nfsAzureFile"
JAVA_COMPONENT_RESOURCE_TYPE = "javaComponents"

MAXIMUM_SECRET_LENGTH = 20
MAXIMUM_CONTAINER_APP_NAME_LENGTH = 32
Expand Down Expand Up @@ -128,3 +129,6 @@

DEFAULT_CONNECTED_CLUSTER_EXTENSION_NAME = "containerapp-ext"
DEFAULT_CONNECTED_CLUSTER_EXTENSION_NAMESPACE = "containerapp-ns"

JAVA_COMPONENT_CONFIG = "SpringCloudConfig"
JAVA_COMPONENT_EUREKA = "SpringCloudEureka"
134 changes: 134 additions & 0 deletions src/containerapp/azext_containerapp/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -1188,3 +1188,137 @@
--image imageName \\
--workload-profile-name my-wlp
"""

# Java Components Commands
helps['containerapp env java-component'] = """
type: group
short-summary: Commands to manage Java components within the environment.
"""

helps['containerapp env java-component list'] = """
type: command
short-summary: List all Java components within the environment.
examples:
- name: List all Java components within an environment.
text: |
az containerapp env java-component list -g MyResourceGroup --environment MyEnvironment
"""

helps['containerapp env java-component spring-cloud-config'] = """
type: group
short-summary: Commands to manage the Spring Cloud Config for the Container Apps environment.
"""

helps['containerapp env java-component spring-cloud-config create'] = """
type: command
short-summary: Command to create the Spring Cloud Config.
examples:
- name: Create a Spring Cloud Config.
text: |
az containerapp env java-component spring-cloud-config create -g MyResourceGroup \\
-n MyJavaComponentName \\
--environment MyEnvironment \\
--configuration PropertyName1=Value1 PropertyName2=Value2
"""

helps['containerapp env java-component spring-cloud-config delete'] = """
type: command
short-summary: Command to delete the Spring Cloud Config.
examples:
- name: Delete a Spring Cloud Config.
text: |
az containerapp env java-component spring-cloud-config delete -g MyResourceGroup \\
-n MyJavaComponentName \\
--environment MyEnvironment
"""

helps['containerapp env java-component spring-cloud-config show'] = """
type: command
short-summary: Command to show the Spring Cloud Config.
examples:
- name: Show a Spring Cloud Config.
text: |
az containerapp env java-component spring-cloud-config show -g MyResourceGroup \\
-n MyJavaComponentName \\
--environment MyEnvironment
"""

helps['containerapp env java-component spring-cloud-config update'] = """
type: command
short-summary: Command to update the Spring Cloud Config.
examples:
- name: Delete all configurations of the Spring Cloud Config.
text: |
az containerapp env java-component spring-cloud-config update -g MyResourceGroup \\
-n MyJavaComponentName \\
--environment MyEnvironment \\
--configuration
- name: Update a Spring Cloud Config with custom configurations.
text: |
az containerapp env java-component spring-cloud-config update -g MyResourceGroup \\
-n MyJavaComponentName \\
--environment MyEnvironment \\
--configuration PropertyName1=Value1 PropertyName2=Value2
"""

helps['containerapp env java-component spring-cloud-eureka'] = """
type: group
short-summary: Commands to manage the Spring Cloud Eureka for the Container Apps environment.
"""

helps['containerapp env java-component spring-cloud-eureka create'] = """
type: command
short-summary: Command to create the Spring Cloud Eureka.
examples:
- name: Create a Spring Cloud Eureka with default configuration.
text: |
az containerapp env java-component spring-cloud-eureka create -g MyResourceGroup \\
-n MyJavaComponentName \\
--environment MyEnvironment
- name: Create a Spring Cloud Eureka with custom configurations.
text: |
az containerapp env java-component spring-cloud-eureka create -g MyResourceGroup \\
-n MyJavaComponentName \\
--environment MyEnvironment \\
--configuration PropertyName1=Value1 PropertyName2=Value2
"""

helps['containerapp env java-component spring-cloud-eureka delete'] = """
type: command
short-summary: Command to delete the Spring Cloud Eureka.
examples:
- name: Delete a Spring Cloud Eureka.
text: |
az containerapp env java-component spring-cloud-eureka delete -g MyResourceGroup \\
-n MyJavaComponentName \\
--environment MyEnvironment
"""

helps['containerapp env java-component spring-cloud-eureka show'] = """
type: command
short-summary: Command to show the Spring Cloud Eureka.
examples:
- name: Show a Spring Cloud Eureka.
text: |
az containerapp env java-component spring-cloud-eureka show -g MyResourceGroup \\
-n MyJavaComponentName \\
--environment MyEnvironment
"""

helps['containerapp env java-component spring-cloud-eureka update'] = """
type: command
short-summary: Command to update the Spring Cloud Eureka.
examples:
- name: Delete all configurations of the Spring Cloud Eureka.
text: |
az containerapp env java-component spring-cloud-eureka update -g MyResourceGroup \\
-n MyJavaComponentName \\
--environment MyEnvironment \\
--configuration
- name: Update a Spring Cloud Eureka with custom configurations.
text: |
az containerapp env java-component spring-cloud-eureka update -g MyResourceGroup \\
-n MyJavaComponentName \\
--environment MyEnvironment \\
--configuration PropertyName1=Value1 PropertyName2=Value2
"""
8 changes: 7 additions & 1 deletion src/containerapp/azext_containerapp/_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -539,4 +539,10 @@
ManagedServiceIdentity = {
"type": None, # 'None', 'SystemAssigned', 'UserAssigned', 'SystemAssigned,UserAssigned'
"userAssignedIdentities": None # {string: UserAssignedIdentity}
}
}

JavaComponent = {
"properties": {
"componentType": None
}
}
12 changes: 9 additions & 3 deletions src/containerapp/azext_containerapp/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def load_arguments(self, _):

# Springboard
with self.argument_context('containerapp create', arg_group='Service Binding', is_preview=True) as c:
c.argument('service_bindings', nargs='*', options_list=['--bind'], help="Space separated list of services(bindings) to be connected to this app. e.g. SVC_NAME1[:BIND_NAME1] SVC_NAME2[:BIND_NAME2]...")
c.argument('service_bindings', nargs='*', options_list=['--bind'], help="Space separated list of services, bindings or Java components to be connected to this app. e.g. SVC_NAME1[:BIND_NAME1] SVC_NAME2[:BIND_NAME2]...")
c.argument('customized_keys', action=AddCustomizedKeys, nargs='*', help='The customized keys used to change default configuration names. Key is the original name, value is the customized name.')
c.argument('service_type', help="The service information for dev services.")
c.ignore('service_type')
Expand All @@ -53,9 +53,9 @@ def load_arguments(self, _):

# Springboard
with self.argument_context('containerapp update', arg_group='Service Binding', is_preview=True) as c:
c.argument('service_bindings', nargs='*', options_list=['--bind'], help="Space separated list of services(bindings) to be connected to this app. e.g. SVC_NAME1[:BIND_NAME1] SVC_NAME2[:BIND_NAME2]...")
c.argument('service_bindings', nargs='*', options_list=['--bind'], help="Space separated list of services, bindings or Java components to be connected to this app. e.g. SVC_NAME1[:BIND_NAME1] SVC_NAME2[:BIND_NAME2]...")
c.argument('customized_keys', action=AddCustomizedKeys, nargs='*', help='The customized keys used to change default configuration names. Key is the original name, value is the customized name.')
c.argument('unbind_service_bindings', nargs='*', options_list=['--unbind'], help="Space separated list of services(bindings) to be removed from this app. e.g. BIND_NAME1...")
c.argument('unbind_service_bindings', nargs='*', options_list=['--unbind'], help="Space separated list of services, bindings or Java components to be removed from this app. e.g. BIND_NAME1...")

with self.argument_context('containerapp env', arg_group='Virtual Network') as c:
c.argument('infrastructure_resource_group', options_list=['--infrastructure-resource-group', '-i'], help='Name for resource group that will contain infrastructure resources. If not provided, a resource group name will be generated.', is_preview=True)
Expand Down Expand Up @@ -289,3 +289,9 @@ def load_arguments(self, _):
with self.argument_context('containerapp github-action add') as c:
c.argument('build_env_vars', nargs='*', help="A list of environment variable(s) for the build. Space-separated values in 'key=value' format.",
validator=validate_build_env_vars, is_preview=True)

with self.argument_context('containerapp env java-component') as c:
c.argument('java_component_name', options_list=['--name', '-n'], help="The Java component name.")
c.argument('environment_name', options_list=['--environment'], help="The environment name.")
c.argument('resource_group_name', arg_type=resource_group_name_type, id_part=None)
c.argument('configuration', nargs="*", help="Java component configuration. Configuration must be in format \"<propertyName>=<value> <propertyName>=<value> ...\".")
Loading

0 comments on commit 371ecd0

Please sign in to comment.