Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/origin/shiqiu/javaComponent2024…
Browse files Browse the repository at this point in the history
…' into shiqiu/JavaComponentFinal
  • Loading branch information
ShichaoQiu committed Jan 26, 2024
2 parents 302b9d5 + 9d9dec6 commit b9bb598
Show file tree
Hide file tree
Showing 10 changed files with 438 additions and 10 deletions.
117 changes: 117 additions & 0 deletions src/containerapp/azext_containerapp/_clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -843,3 +843,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
3 changes: 3 additions & 0 deletions src/containerapp/azext_containerapp/_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,6 @@

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

JAVA_COMPONENT_CONFIG = "SpringCloudConfig"
JAVA_COMPONENT_EUREKA = "SpringCloudEureka"
61 changes: 61 additions & 0 deletions src/containerapp/azext_containerapp/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -1195,3 +1195,64 @@
--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.
"""

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.
"""

helps['containerapp env java-component spring-cloud-config delete'] = """
type: command
short-summary: Command to delete the Spring Cloud Config.
"""

helps['containerapp env java-component spring-cloud-config show'] = """
type: command
short-summary: Command to show the Spring Cloud Config.
"""

helps['containerapp env java-component spring-cloud-config update'] = """
type: command
short-summary: Command to update the Spring Cloud Config.
"""

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.
"""

helps['containerapp env java-component spring-cloud-eureka delete'] = """
type: command
short-summary: Command to delete the Spring Cloud Eureka.
"""

helps['containerapp env java-component spring-cloud-eureka show'] = """
type: command
short-summary: Command to show the Spring Cloud Eureka.
"""

helps['containerapp env java-component spring-cloud-eureka update'] = """
type: command
short-summary: Command to update the Spring Cloud Eureka.
"""
12 changes: 12 additions & 0 deletions src/containerapp/azext_containerapp/_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -524,3 +524,15 @@
"name": None,
"type": None
}

JavaComponent = {
"properties": {
"componentType": None,
"configurations": None # list of JavaComponentConfiguration
}
}

JavaComponentConfiguration = {
"propertyName": None,
"value": 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 @@ -26,7 +26,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 @@ -47,9 +47,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 @@ -247,3 +247,9 @@ def load_arguments(self, _):
c.argument('dapr_component_name', help="The Dapr component name.")
c.argument('environment_name', options_list=['--name', '-n'], help="The environment name.")
c.argument('yaml', type=file_type, help='Path to a .yaml file with the configuration of a Dapr component. All other parameters will be ignored. For an example, see https://learn.microsoft.com/en-us/azure/container-apps/dapr-overview?tabs=bicep1%2Cyaml#component-schema')

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> ...\".")
20 changes: 17 additions & 3 deletions src/containerapp/azext_containerapp/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from msrestazure.tools import parse_resource_id, is_valid_resource_id

from ._managed_service_utils import ManagedRedisUtils, ManagedCosmosDBUtils, ManagedPostgreSQLFlexibleUtils, ManagedMySQLFlexibleUtils
from ._clients import ConnectedEnvCertificateClient, ContainerAppPreviewClient
from ._clients import ConnectedEnvCertificateClient, ContainerAppPreviewClient, JavaComponentPreviewClient
from ._client_factory import custom_location_client_factory, k8s_extension_client_factory, providers_client_factory, \
connected_k8s_client_factory, handle_non_404_status_code_exception
from ._models import OryxRunImageTagProperty
Expand Down Expand Up @@ -87,7 +87,12 @@ def process_service(cmd, resource_list, service_name, arg_dict, subscription_id,
if customized_keys:
service_bind["customizedKeys"] = customized_keys
service_bindings_def_list.append(service_bind)

elif service["type"] == "Microsoft.App/managedEnvironments/javaComponents":
service_bind = {
"serviceId": service["id"],
"name": binding_name
}
service_bindings_def_list.append(service_bind)
else:
raise ValidationError("Service not supported")
break
Expand Down Expand Up @@ -148,7 +153,7 @@ def check_unique_bindings(cmd, service_connectors_def_list, service_bindings_def
return True


def parse_service_bindings(cmd, service_bindings_list, resource_group_name, name, customized_keys=None):
def parse_service_bindings(cmd, service_bindings_list, resource_group_name, name, containerapp_def, customized_keys=None):
# Make it return both managed and dev bindings
service_bindings_def_list = []
service_connector_def_list = []
Expand Down Expand Up @@ -200,6 +205,15 @@ def parse_service_bindings(cmd, service_bindings_list, resource_group_name, name

subscription_id = get_subscription_id(cmd.cli_ctx)

# Add Java component into the resource_list
parsed_managed_env = parse_resource_id(containerapp_def["properties"]["environmentId"])
managed_env_name = parsed_managed_env['name']
managed_env_rg = parsed_managed_env['resource_group']

java_component_list = JavaComponentPreviewClient.list(cmd, managed_env_rg, managed_env_name)
for java_component in java_component_list:
resource_list.append({"name": java_component["name"], "type": java_component["type"], "id": java_component["id"]})

# Will work for both create and update
process_service(cmd, resource_list, service_name, arg_dict, subscription_id, resource_group_name,
name, binding_name, service_connector_def_list, service_bindings_def_list, customized_keys)
Expand Down
15 changes: 15 additions & 0 deletions src/containerapp/azext_containerapp/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,18 @@ def load_command_table(self, _):
g.custom_command('list', 'connected_env_list_storages')
g.custom_command('set', 'connected_env_create_or_update_storage', supports_no_wait=True, exception_handler=ex_handler_factory())
g.custom_command('remove', 'connected_env_remove_storage', supports_no_wait=True, confirmation=True, exception_handler=ex_handler_factory())

with self.command_group('containerapp env java-component', is_preview=True) as g:
g.custom_command('list', 'list_java_components')

with self.command_group('containerapp env java-component spring-cloud-config') as g:
g.custom_command('create', 'create_spring_cloud_config', supports_no_wait=True)
g.custom_command('update', 'update_spring_cloud_config', supports_no_wait=True)
g.custom_show_command('show', 'show_spring_cloud_config')
g.custom_command('delete', 'delete_spring_cloud_config', confirmation=True, supports_no_wait=True)

with self.command_group('containerapp env java-component spring-cloud-eureka') as g:
g.custom_command('create', 'create_spring_cloud_eureka', supports_no_wait=True)
g.custom_command('update', 'update_spring_cloud_eureka', supports_no_wait=True)
g.custom_show_command('show', 'show_spring_cloud_eureka')
g.custom_command('delete', 'delete_spring_cloud_eureka', confirmation=True, supports_no_wait=True)
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,7 @@ def set_up_service_binds(self):
self.get_argument_service_bindings(),
self.get_argument_resource_group_name(),
self.get_argument_name(),
self.containerapp_def,
self.get_argument_customized_keys())
self.set_argument_service_connectors_def_list(service_connectors_def_list)
unique_bindings = check_unique_bindings(self.cmd, service_connectors_def_list, service_bindings_def_list,
Expand Down Expand Up @@ -1108,7 +1109,7 @@ def set_up_service_bindings(self):
if self.get_argument_service_bindings() is not None:
linker_client = get_linker_client(self.cmd)

service_connectors_def_list, service_bindings_def_list = parse_service_bindings(self.cmd, self.get_argument_service_bindings(), self.get_argument_resource_group_name(), self.get_argument_name(), self.get_argument_customized_keys())
service_connectors_def_list, service_bindings_def_list = parse_service_bindings(self.cmd, self.get_argument_service_bindings(), self.get_argument_resource_group_name(), self.get_argument_name(), self.containerapp_def, self.get_argument_customized_keys())
self.set_argument_service_connectors_def_list(service_connectors_def_list)
service_bindings_used_map = {update_item["name"]: False for update_item in service_bindings_def_list}

Expand Down
Loading

0 comments on commit b9bb598

Please sign in to comment.