Skip to content

Commit

Permalink
Merge pull request #68 from blackchoey/frank/support-custom-metadata-…
Browse files Browse the repository at this point in the history
…export-only

feat: support custom metadata export only
  • Loading branch information
frankqianms authored Sep 26, 2024
2 parents 02827ef + 865d924 commit 738f46a
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ class Export(AAZCommand):
:example: Export Metadata Schema assigned to environment
az apic metadata export -g api-center-test -n contosoeuap --assignments environment --file-name filename.json
:example: Export Custom Metadata Schema Only
az apic metadata export -g api-center-test -n contosoeuap --assignments api --file-name filename.json --custom-metadata-only
"""

_aaz_info = {
Expand Down
15 changes: 13 additions & 2 deletions src/apic-extension/azext_apic_extension/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from knack.log import get_logger
from knack.util import CLIError
import chardet
from azure.cli.core.aaz._arg import AAZStrArg
from azure.cli.core.aaz._arg import AAZStrArg, AAZBoolArg
from .command_patches import ImportAPIDefinitionExtension
from .command_patches import ExportAPIDefinitionExtension
from .command_patches import ExportMetadataExtension
Expand Down Expand Up @@ -105,6 +105,12 @@ def _build_arguments_schema(cls, *args, **kwargs):
required=True,
registered=True
)
args_schema.custom_metadata_only = AAZBoolArg(
options=["--custom-metadata-only"],
help='Export only custom metadata.',
required=False,
blank=True
)
return args_schema

def _output(self, *args, **kwargs):
Expand All @@ -118,9 +124,14 @@ def _output(self, *args, **kwargs):
if response_format == 'link':
getReponse = requests.get(exportedResults, timeout=10)
if getReponse.status_code == 200:
exportedResults = getReponse.content.decode()
content = json.loads(getReponse.content.decode())
# Check if custom metadata only
exportedResults = content.get('properties').get('customProperties', {}) if arguments.custom_metadata_only else content
else:
logger.error('Error while fetching the results from the link. Status code: %s', getReponse.status_code)
else:
# Check if custom metadata only
exportedResults = json.loads(exportedResults).get('properties').get('customProperties', {}) if arguments.custom_metadata_only else exportedResults

if arguments.source_profile:
try:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
interactions:
- request:
body: '{"assignedTo": "api"}'
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
CommandName:
- apic metadata export
Connection:
- keep-alive
Content-Length:
- '21'
Content-Type:
- application/json
ParameterSetName:
- -g -n --assignments --file-name --custom-metadata-only
User-Agent:
- AZURECLI/2.63.0 azsdk-python-core/1.28.0 Python/3.11.9 (Windows-10-10.0.22631-SP0)
method: POST
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clirg000001/providers/Microsoft.ApiCenter/services/clitest000002/exportMetadataSchema?api-version=2024-03-01
response:
body:
string: '{"format":"json-schema","value":"{\"type\":\"object\",\"properties\":{\"Name\":{\"type\":\"string\"},\"WorkspaceName\":{\"type\":\"string\"},\"Title\":{\"type\":\"string\"},\"Summary\":{\"type\":\"string\"},\"Description\":{\"type\":\"string\"},\"Kind\":{\"type\":\"string\"},\"LifecycleStage\":{\"type\":\"string\",\"enum\":[\"design\",\"development\",\"testing\",\"preview\",\"production\",\"deprecated\",\"retired\"]},\"TermsOfService\":{\"type\":\"object\",\"properties\":{\"url\":{\"description\":\"URL
pointing to the terms of service.\",\"type\":\"string\",\"maxLength\":200,\"format\":\"uri\"}}},\"License\":{\"type\":\"object\",\"properties\":{\"name\":{\"description\":\"Name
of the license.\",\"type\":\"string\",\"maxLength\":50},\"url\":{\"description\":\"URL
pointing to the license details. The URL field is mutually exclusive of the
identifier field.\",\"type\":\"string\",\"maxLength\":200,\"format\":\"uri\"},\"identifier\":{\"description\":\"SPDX
license information for the API. The identifier field is mutually exclusive
of the URL field.\",\"type\":\"string\",\"maxLength\":200,\"format\":\"uri\"}}},\"ExternalDocumentation\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"title\":{\"description\":\"Title
of the documentation.\",\"type\":\"string\",\"maxLength\":50},\"description\":{\"description\":\"Description
of the documentation.\",\"type\":\"string\",\"maxLength\":1000},\"url\":{\"description\":\"URL
pointing to the documentation.\",\"type\":\"string\",\"maxLength\":200,\"format\":\"uri\"}}}},\"Contacts\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"name\":{\"description\":\"Name
of the contact.\",\"type\":\"string\",\"maxLength\":100},\"url\":{\"description\":\"URL
for the contact.\",\"type\":\"string\",\"maxLength\":200,\"format\":\"uri\"},\"email\":{\"description\":\"Email
address for the contact.\",\"type\":\"string\",\"maxLength\":100,\"format\":\"email\"}}}},\"CustomPropertiesData\":{},\"ApiSourceName\":{\"type\":\"string\"},\"CatalogNameTypeSafe\":{\"type\":\"object\",\"additionalProperties\":false,\"properties\":{\"Name\":{\"type\":\"string\"}}},\"CatalogName\":{\"type\":\"string\"},\"SubscriptionId\":{\"type\":\"string\"},\"SubscriptionIdTypeSafe\":{\"type\":\"string\"},\"ResourceGroupName\":{\"type\":\"string\"},\"ResourceGroupNameTypeSafe\":{\"type\":\"object\",\"additionalProperties\":false,\"properties\":{\"Name\":{\"type\":\"string\"}}},\"ETag\":{\"type\":\"string\"},\"Created\":{\"type\":\"string\",\"format\":\"date-time\"},\"Updated\":{\"type\":\"string\",\"format\":\"date-time\"},\"CreatedBy\":{\"type\":\"string\"},\"UpdatedBy\":{\"type\":\"string\"},\"customProperties\":{\"type\":\"object\",\"properties\":{\"clitest000003\":{\"type\":\"boolean\",\"title\":\"Public
Facing\"}},\"unevaluatedProperties\":false,\"required\":[\"clitest000003\"]}}}"}'
headers:
api-supported-versions:
- 2023-07-01-preview, 2024-03-01, 2024-03-15-preview
cache-control:
- no-cache
content-length:
- '2865'
content-type:
- application/json; charset=utf-8
date:
- Thu, 26 Sep 2024 02:30:22 GMT
expires:
- '-1'
pragma:
- no-cache
strict-transport-security:
- max-age=31536000; includeSubDomains
vary:
- Accept-Encoding
x-cache:
- CONFIG_NOCACHE
x-content-type-options:
- nosniff
x-ms-ratelimit-remaining-subscription-writes:
- '1199'
x-msedge-ref:
- 'Ref A: BB450A2E8FCB40B6A0514E0031D51D56 Ref B: MAA201060516029 Ref C: 2024-09-26T02:30:22Z'
x-powered-by:
- ASP.NET
status:
code: 200
message: OK
version: 1
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,27 @@ def test_metadata_export(self):
finally:
os.remove(self.kwargs['filename'])

@ResourceGroupPreparer(name_prefix="clirg", location=TEST_REGION, random_name_length=32)
@ApicServicePreparer()
@ApicMetadataPreparer()
def test_metadata_export_with_custom_metadata_only(self):
self.kwargs.update({
'filename': 'metadata_export.json'
})
self.cmd('az apic metadata export -g {rg} -n {s} --assignments api --file-name {filename} --custom-metadata-only')

try:
with open(self.kwargs['filename'], 'r') as f:
data = json.load(f)

assert 'properties' in data, "properties not found in customProperties"
assert data['type'] == 'object', "Type of the customProperties does not match the expected type"
assert len(data['properties']) == 1, "The number of properties in customProperties does not match the expected number"
assert data['unevaluatedProperties'] == False, "unevaluatedProperties does not match the expected value"
assert len(data['required']) == 1, "The number of required does not match the expected number"
finally:
os.remove(self.kwargs['filename'])

@ResourceGroupPreparer(name_prefix="clirg", location=TEST_REGION, random_name_length=32)
@ApicServicePreparer()
def test_examples_create_metadata_1(self):
Expand Down

0 comments on commit 738f46a

Please sign in to comment.