Skip to content
Closed
4 changes: 2 additions & 2 deletions src/azure-cli-testsdk/azure/cli/testsdk/preparers.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ def create_resource(self, name, **kwargs):
'module': module}
if 'ENV_JOB_NAME' in os.environ:
tags['job'] = os.environ['ENV_JOB_NAME']
tags = ' '.join(['{}={}'.format(key, value) for key, value in tags.items()])
if self.additional_tags is not None:
tags = tags.join(['{}={}'.format(key, value) for key, value in self.additional_tags.items()])
tags.update(self.additional_tags)
tags = ' '.join(['{}={}'.format(key, value) for key, value in tags.items()])
template = 'az group create --location {} --name {} --tag ' + tags
if self.subscription:
template += ' --subscription {} '.format(self.subscription)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ def cf_api(cli_ctx, *_):
return cf_apim(cli_ctx).api


def cf_api_policy(cli_ctx, *_):
return cf_apim(cli_ctx).api_policy


def cf_product(cli_ctx, *_):
return cf_apim(cli_ctx).product

Expand Down
75 changes: 75 additions & 0 deletions src/azure-cli/azure/cli/command_modules/apim/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
short-summary: Manage Azure API Management API's.
"""

helps['apim policy'] = """
type: group
short-summary: Manage Azure API Management API Policies.
"""

helps['apim product api'] = """
type: group
short-summary: Manage Azure API Management Product's APIs.
Expand Down Expand Up @@ -252,6 +257,76 @@
az apim api export -g MyResourceGroup --service-name MyApim --api-id MyApi --export-format OpenApiJson --file-path path
"""

helps['apim policy set'] = """
type: command
short-summary: Create or update policy for the given scope.
examples:
- name: Create or update policy for API Operation
text: |-
az apim policy set -g MyResourceGroup -n MyApim --api-id MyApi --operation-id MyOp --specification-path PathToXmlFile
- name: Create or update policy for API
text: |-
az apim policy set -g MyResourceGroup -n MyApim --api-id MyApi --specification-path PathToXmlFile
- name: Create or update global policy
text: |-
az apim policy set -g MyResourceGroup -n MyApim --specification-path PathToXmlFile
"""

helps['apim policy show'] = """
type: command
short-summary: Get policy for the given scope.
examples:
- name: Get policy for API Operation
text: |-
az apim policy show -g MyResourceGroup -n MyApim --api-id MyApi --operation-id MyOp
- name: Get policy for API
text: |-
az apim policy show -g MyResourceGroup -n MyApim --api-id MyApi
- name: Get global policy
text: |-
az apim policy show -g MyResourceGroup -n MyApim
"""

helps['apim policy delete'] = """
type: command
short-summary: Delete policy for the given scope.
examples:
- name: Delete policy for API Operation
text: |-
az apim policy delete -g MyResourceGroup -n MyApim --api-id MyApi --operation-id MyOp
- name: Delete policy for API
text: |-
az apim policy delete -g MyResourceGroup -n MyApim --api-id MyApi
- name: Delete global policy
text: |-
az apim policy delete -g MyResourceGroup -n MyApim
"""

helps['apim policy list'] = """
type: command
short-summary: List policies for the given scope.
examples:
- name: List policies for API Operation
text: |-
az apim policy list -g MyResourceGroup -n MyApim --api-id MyApi --operation-id MyOp
- name: List policies for API
text: |-
az apim policy list -g MyResourceGroup -n MyApim --api-id MyApi
- name: List global policies
text: |-
az apim policy list -g MyResourceGroup -n MyApim
"""

helps['apim policy wait'] = """
type: command
short-summary: Place the CLI in a waiting state until a condition of an apim api is met.
examples:
- name: Place the CLI in a waiting state until a condition of a apim api is met.
text: |
az apim policy wait --created --api-id MyApi --policy-id MyPolicy --name MyApim --resource-group MyResourceGroup
crafted: true
"""

helps['apim product api list'] = """
type: command
short-summary: Lists a collection of the APIs associated with a product.
Expand Down
15 changes: 14 additions & 1 deletion src/azure-cli/azure/cli/command_modules/apim/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
resource_group_name_type,
get_three_state_flag)

from azure.mgmt.apimanagement.models import (SkuType, VirtualNetworkType, Protocol, ApiType, ProductState)
from azure.mgmt.apimanagement.models import (SkuType, VirtualNetworkType, Protocol, ApiType, ProductState, PolicyContentFormat)
from azure.cli.command_modules.apim.actions import (TemplateParameter)


Expand Down Expand Up @@ -314,6 +314,19 @@ def load_arguments(self, _):
c.argument('file_path', options_list=['--file-path', '-f'],
help='File path specified to export the API.')

with self.argument_context('apim policy') as c:
c.argument('api_id', arg_type=api_id)
c.argument('operation_id', help='Operation identifier within an API. Must be unique in the current API Management service instance.')
c.argument('specification_path', help='Contents of the Policy as defined by the format.')
c.argument('policy_format', arg_type=get_enum_type(PolicyContentFormat), help='Format of the policy content.')
c.argument('policy_id', help='Policy identifier within an API. Must be unique in the current API context.')

with self.argument_context('apim policy show') as c:
c.argument('file_path', help='Path to the file where the policy content will be saved. If not specified, the policy content will be printed to the standard output.')

with self.argument_context('apim policy delete') as c:
c.argument('if_match', help='ETag of the Entity.')

with self.argument_context('apim product api list') as c:
c.argument('service_name', options_list=['--service-name', '-n'],
help="The name of the api management service instance", id_part=None)
Expand Down
16 changes: 15 additions & 1 deletion src/azure-cli/azure/cli/command_modules/apim/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

from azure.cli.core.commands import CliCommandType
from azure.cli.command_modules.apim._format import (service_output_format)
from azure.cli.command_modules.apim._client_factory import (cf_service, cf_api, cf_product, cf_nv, cf_apiops,
from azure.cli.command_modules.apim._client_factory import (cf_service, cf_api, cf_api_policy,
cf_product, cf_nv, cf_apiops,
cf_apirelease, cf_apirevision, cf_apiversionset,
cf_apischema, cf_ds, cf_graphqlapiresolver,
cf_graphqlapiresolverpolicy)
Expand All @@ -25,6 +26,11 @@ def load_command_table(self, _):
client_factory=cf_api
)

api_policy_sdk = CliCommandType(
operations_tmpl='azure.mgmt.apimanagement.operations#ApiPolicyOperations.{}',
client_factory=cf_api_policy
)

api_schema = CliCommandType(
operations_tmpl='azure.mgmt.apimanagement.operations#ApiSchemaOperations.{}',
client_factory=cf_apischema
Expand Down Expand Up @@ -106,6 +112,14 @@ def load_command_table(self, _):
setter_name='begin_create_or_update', getter_name='get', supports_no_wait=True)
g.wait_command('wait')

with self.command_group('apim policy', api_policy_sdk) as g:
g.custom_show_command('show', 'apim_api_policy_show')
g.custom_command('set', 'apim_api_policy_set', supports_no_wait=True)
g.custom_command('delete', 'apim_api_policy_delete', confirmation=True, supports_no_wait=True)
g.custom_command('list', 'apim_api_policy_list')
g.custom_command('get-etag', 'apim_api_policy_get_entity')
g.wait_command('wait')

with self.command_group('apim product api', api_sdk) as g:
g.custom_command('list', 'apim_product_api_list')
g.custom_command('check', 'apim_product_api_check_association')
Expand Down
142 changes: 142 additions & 0 deletions src/azure-cli/azure/cli/command_modules/apim/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,148 @@ def api_export_result_to_dict(api_export_result):
}


def _get_policy_context(client, api_id, operation_id):
# Helper function that returns the correct context for policy operations

if api_id is None and operation_id is not None:
raise RequiredArgumentMissingError(
"Please specify api-id when operation-id is specified.")

if api_id and operation_id:
return client.api_operation_policy
if api_id:
return client.api_policy

return client.policy


# Api Policy Operations
def apim_api_policy_set(client, resource_group_name, service_name,
specification_path, api_id=None,
operation_id=None, policy_id="policy",
policy_format=None, no_wait=False):
"""Sets or updates an API Policy. """
try:
with open(specification_path, 'r') as api_file:
content_value = api_file.read()
except OSError as e:
logger.warning("Error opening policy file: %s", e)

parameters = PolicyContract(
format=policy_format,
value=content_value
)

# Select the method based on the presence of api_id and operation_id
module_context = _get_policy_context(client, api_id, operation_id)

# Prepare the arguments dynamically based on use case
arguments = {
"resource_group_name": resource_group_name,
"service_name": service_name,
"policy_id": policy_id,
"parameters": parameters
}

if api_id:
arguments["api_id"] = api_id
if operation_id:
arguments["operation_id"] = operation_id

# Use the selected method
return sdk_no_wait(no_wait, module_context.create_or_update, **arguments)


def apim_api_policy_delete(client, resource_group_name,
service_name, api_id=None,
operation_id=None, policy_id="policy",
if_match=None, no_wait=False):
"""Deletes an API Policy. """

module_context = _get_policy_context(client, api_id, operation_id)
arguments = {
"resource_group_name": resource_group_name,
"service_name": service_name,
"policy_id": policy_id,
"if_match": "*" if if_match is None else if_match
}

if api_id:
arguments["api_id"] = api_id
if operation_id:
arguments["operation_id"] = operation_id

return sdk_no_wait(no_wait, module_context.delete, **arguments)


def apim_api_policy_show(client, resource_group_name,
service_name, api_id=None,
operation_id=None, policy_id="policy", file_path=None):
"""Shows the details of an API Policy. """

module_context = _get_policy_context(client, api_id, operation_id)

arguments = {
"resource_group_name": resource_group_name,
"service_name": service_name,
"policy_id": policy_id
}

if api_id:
arguments["api_id"] = api_id
if operation_id:
arguments["operation_id"] = operation_id

policy = module_context.get(**arguments)

if file_path is not None:
logger.warning("Writing policy to file: %s", file_path)
try:
with open(file_path, 'w') as f:
f.write(policy.value)
except OSError as e:
logger.warning("Error writing policy to file: %s", e)

return logger.warning("Policy export complete. Policy written to file: %s", file_path)
return policy


def apim_api_policy_list(client, resource_group_name,
service_name, api_id=None, operation_id=None):
""" List Policies for the given scope. """

module_context = _get_policy_context(client, api_id, operation_id)

if api_id and operation_id:
return module_context.list_by_operation(resource_group_name, service_name, api_id, operation_id)
if api_id:
return module_context.list_by_api(resource_group_name, service_name, api_id)

return module_context.list_by_service(resource_group_name, service_name)


def apim_api_policy_get_entity(client, resource_group_name,
service_name, policy_id="policy",
api_id=None, operation_id=None):

""" Gets the entity state (etag) version of the API Policy. """

module_context = _get_policy_context(client, api_id, operation_id)

arguments = {
"resource_group_name": resource_group_name,
"service_name": service_name,
"policy_id": policy_id
}

if api_id:
arguments["api_id"] = api_id
if operation_id:
arguments["operation_id"] = operation_id

return module_context.get_entity_tag(**arguments)


# Product API Operations
def apim_product_api_list(client, resource_group_name, service_name, product_id):

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!--
This is a test policy file for Azure API Management.
-->
<!-- Add policies as children to the <inbound>, <outbound>, <backend>, and <on-error> elements -->
<policies>
<!-- Throttle, authorize, validate, cache, or transform the requests -->
<inbound>
</inbound>
<!-- Control if and how the requests are forwarded to services -->
<backend>
</backend>
<!-- Customize the responses -->
<outbound>
</outbound>
<!-- Handle exceptions and customize error responses -->
<on-error>
</on-error>
</policies>
Loading