Skip to content

Commit

Permalink
Dapr Commands (#23)
Browse files Browse the repository at this point in the history
* Added ingress subgroup.

* Added help for ingress.

* Fixed ingress traffic help.

* Added registry commands.

* Updated registry remove util to clear secrets if none remaining. Added warning when updating existing registry. Added registry help.

* Changed registry delete to remove.

* Added error message if user tries to remove non assigned registry.

* Changed registry add back to registry set.

* Added secret subgroup commands.

* Removed yaml support from secret set.

* Changed secret add to secret set. Updated consistency between secret set and secret delete. Added secret help. Require at least one secret passed with --secrets for secret commands.

* Changed param name for secret delete from --secrets to --secret-names. Updated help.

* Changed registry remove to registry delete.

* Fixed bug in registry delete.

* Added revision mode set and revision copy.

* Added dapr enable and dapr disable. Need to test more.

* Added list, show, set dapr component. Added dapr enable, disable.

* Added delete dapr delete.

* Added helps and param text.

* Changed dapr delete to dapr remove to match with dapr set.

* Commented out managed identity for whl file.

* Uncommented.

Co-authored-by: Haroon Feisal <haroonfeisal@microsoft.com>
  • Loading branch information
2 people authored and calvinsID committed Mar 24, 2022
1 parent 7d8b9ba commit bc8c58b
Show file tree
Hide file tree
Showing 7 changed files with 369 additions and 3 deletions.
119 changes: 119 additions & 0 deletions src/containerapp/azext_containerapp/_clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -603,3 +603,122 @@ def delete(cls, cmd, resource_group_name, name, headers, no_wait=False):
pass
logger.warning('Containerapp github action successfully deleted')
return

class DaprComponentClient():
@classmethod
def create_or_update(cls, cmd, resource_group_name, environment_name, name, dapr_component_envelope, no_wait=False):
#create_or_update.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.App/managedEnvironments/{environmentName}/daprComponents/{name}'}

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

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

if no_wait:
return r.json()
elif r.status_code == 201:
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/managedEnvironments/{}/daprComponents/{}?api-version={}"
request_url = url_fmt.format(
management_hostname.strip('/'),
sub_id,
resource_group_name,
environment_name,
name,
api_version)
return poll(cmd, request_url, "inprogress")

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
api_version = NEW_API_VERSION
sub_id = get_subscription_id(cmd.cli_ctx)
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/managedEnvironments/{}/daprComponents/{}?api-version={}"
request_url = url_fmt.format(
management_hostname.strip('/'),
sub_id,
resource_group_name,
environment_name,
name,
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]:
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/managedEnvironments/{}/daprComponents/{}?api-version={}"
request_url = url_fmt.format(
management_hostname.strip('/'),
sub_id,
resource_group_name,
environment_name,
name,
api_version)

if r.status_code == 202:
from azure.cli.core.azclierror import ResourceNotFoundError
try:
poll(cmd, request_url, "cancelled")
except ResourceNotFoundError:
pass
logger.warning('Dapr component successfully deleted')
return

@classmethod
def show(cls, cmd, resource_group_name, environment_name, name):
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
api_version = NEW_API_VERSION
sub_id = get_subscription_id(cmd.cli_ctx)
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/managedEnvironments/{}/daprComponents/{}?api-version={}"
request_url = url_fmt.format(
management_hostname.strip('/'),
sub_id,
resource_group_name,
environment_name,
name,
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, formatter=lambda x: x):
app_list = []

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

r = send_raw_request(cmd.cli_ctx, "GET", request_url)
j = r.json()
for app in j["value"]:
formatted = formatter(app)
app_list.append(formatted)

while j.get("nextLink") is not None:
request_url = j["nextLink"]
r = send_raw_request(cmd.cli_ctx, "GET", request_url)
j = r.json()
for app in j["value"]:
formatted = formatter(app)
app_list.append(formatted)

return app_list

78 changes: 78 additions & 0 deletions src/containerapp/azext_containerapp/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,24 @@
--from-revision PreviousRevisionName --cpu 0.75 --memory 1.5Gi
"""

helps['containerapp revision mode set'] = """
type: command
short-summary: Set the revision mode of a Containerapp.
examples:
- name: Set the revision mode of a Containerapp.
text: |
az containerapp revision set --mode Single -n MyContainerapp -g MyResourceGroup
"""

helps['containerapp revision copy'] = """
type: command
short-summary: Create a revision based on a previous revision.
examples:
- name: Create a revision based on a previous revision.
text: |
az containerapp revision copy -n MyContainerapp -g MyResourceGroup --cpu 0.75 --memory 1.5Gi
"""

# Environment Commands
helps['containerapp env'] = """
type: group
Expand Down Expand Up @@ -456,4 +474,64 @@
examples:
- name: Show the GitHub Actions configuration on a Containerapp.
text: az containerapp github-action show -g MyResourceGroup -n MyContainerapp
"""

# Dapr Commands
helps['containerapp dapr'] = """
type: group
short-summary: Commands to manage Containerapp dapr.
"""

helps['containerapp dapr enable'] = """
type: command
short-summary: Enable dapr for a Containerapp.
examples:
- name: Enable dapr for a Containerapp.
text: |
az containerapp dapr enable -n MyContainerapp -g MyResourceGroup --dapr-app-id my-app-id --dapr-app-port 8080
"""

helps['containerapp dapr disable'] = """
type: command
short-summary: Disable dapr for a Containerapp.
examples:
- name: Disable dapr for a Containerapp.
text: |
az containerapp dapr disable -n MyContainerapp -g MyResourceGroup
"""

helps['containerapp dapr list'] = """
type: command
short-summary: List dapr components for a Containerapp environment.
examples:
- name: List dapr components for a Containerapp environment.
text: |
az containerapp dapr list -g MyResourceGroup --environment-name MyEnvironment
"""

helps['containerapp dapr show'] = """
type: command
short-summary: Show the details of a dapr component.
examples:
- name: Show the details of a dapr component.
text: |
az containerapp dapr show -g MyResourceGroup --dapr-component-name MyDaprComponenetName --environment-name MyEnvironment
"""

helps['containerapp dapr set'] = """
type: command
short-summary: Create or update a dapr component.
examples:
- name: Create a dapr component.
text: |
az containerapp dapr set -g MyResourceGroup --environment-name MyEnv --yaml MyYAMLPath --name MyDaprName
"""

helps['containerapp dapr remove'] = """
type: command
short-summary: Remove a dapr componenet from a Containerapp environment.
examples:
- name: Remove a dapr componenet from a Containerapp environment.
text: |
az containerapp dapr delete -g MyResourceGroup --dapr-component-name MyDaprComponenetName --environment-name MyEnvironment
"""
20 changes: 19 additions & 1 deletion src/containerapp/azext_containerapp/_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,24 @@
"tags": None
}

DaprComponent = {
"properties": {
"componentType": None, #String
"version": None,
"ignoreErrors": None,
"initTimeout": None,
"secrets": None,
"metadata": None,
"scopes": None
}
}

DaprMetadata = {
"key": None, #str
"value": None, #str
"secret_ref": None #str
}

SourceControl = {
"properties": {
"repoUrl": None,
Expand Down Expand Up @@ -211,4 +229,4 @@
"clientSecret": None, # str
"tenantId": None, #str
"subscriptionId": None #str
}
}
7 changes: 7 additions & 0 deletions src/containerapp/azext_containerapp/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,10 @@ def load_arguments(self, _):

with self.argument_context('containerapp secret delete') as c:
c.argument('secret_names', nargs='+', help="A list of secret(s) for the container app. Space-separated secret values names.")

with self.argument_context('containerapp dapr') as c:
c.argument('dapr_app_id', help="The dapr app id.")
c.argument('dapr_app_port', help="The port of your app.")
c.argument('dapr_app_protocol', help="Tells Dapr which protocol your application is using. Allowed values: grpc, http.")
c.argument('dapr_component_name', help="The dapr component name.")
c.argument('environment_name', help="The dapr component environment name.")
17 changes: 17 additions & 0 deletions src/containerapp/azext_containerapp/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,23 @@ def _remove_readonly_attributes(containerapp_def):
elif unneeded_property in containerapp_def['properties']:
del containerapp_def['properties'][unneeded_property]

def _remove_dapr_readonly_attributes(daprcomponent_def):
unneeded_properties = [
"id",
"name",
"type",
"systemData",
"provisioningState",
"latestRevisionName",
"latestRevisionFqdn",
"customDomainVerificationId",
"outboundIpAddresses",
"fqdn"
]

for unneeded_property in unneeded_properties:
if unneeded_property in daprcomponent_def:
del daprcomponent_def[unneeded_property]

def update_nested_dictionary(orig_dict, new_dict):
# Recursively update a nested dictionary. If the value is a list, replace the old list with new list
Expand Down
9 changes: 9 additions & 0 deletions src/containerapp/azext_containerapp/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,12 @@ def load_command_table(self, _):
g.custom_command('show', 'show_secret')
g.custom_command('delete', 'delete_secrets', exception_handler=ex_handler_factory())
g.custom_command('set', 'set_secrets', exception_handler=ex_handler_factory())

with self.command_group('containerapp dapr') as g:
g.custom_command('enable', 'enable_dapr', exception_handler=ex_handler_factory())
g.custom_command('disable', 'disable_dapr', exception_handler=ex_handler_factory())
g.custom_command('list', 'list_dapr_components')
g.custom_command('show', 'show_dapr_component')
g.custom_command('set', 'create_or_update_dapr_component')
g.custom_command('remove', 'remove_dapr_component')

Loading

0 comments on commit bc8c58b

Please sign in to comment.