diff --git a/src/plugins/azgenerator/CodeModelAz.ts b/src/plugins/azgenerator/CodeModelAz.ts index 0ab0a50ec..0c5b3fe66 100644 --- a/src/plugins/azgenerator/CodeModelAz.ts +++ b/src/plugins/azgenerator/CodeModelAz.ts @@ -119,6 +119,7 @@ export interface CodeModelAz MethodParameter_IsList: boolean; MethodParameter_IsSimpleArray: boolean; MethodParameter_IsListOfSimple: boolean; + MethodParameter_IdPart: string; MethodParameter: Parameter; MethodParameters: Array; SubMethodParameter: Parameter; diff --git a/src/plugins/azgenerator/CodeModelAzImpl.ts b/src/plugins/azgenerator/CodeModelAzImpl.ts index 1ebda9ef1..b9078e0e0 100644 --- a/src/plugins/azgenerator/CodeModelAzImpl.ts +++ b/src/plugins/azgenerator/CodeModelAzImpl.ts @@ -7,7 +7,7 @@ import { CodeModelAz, CommandExample, ExampleParam, MethodParam } from "./CodeMo import { CodeModel, SchemaType, Schema, ParameterLocation, Operation, Value, Parameter, VirtualParameter, Property, Request, OperationGroup } from '@azure-tools/codemodel'; import { serialize, deserialize, EnglishPluralizationService, pascalCase } from "@azure-tools/codegen"; import { Session, startSession, Host, Channel } from "@azure-tools/autorest-extension-base"; -import { ToSnakeCase, deepCopy, ToJsonString, Capitalize, ToCamelCase, EscapeString } from '../../utils/helper'; +import { ToSnakeCase, deepCopy, ToJsonString, Capitalize, ToCamelCase, EscapeString, parseResourceId } from '../../utils/helper'; import { values } from "@azure-tools/linq"; import { GenerateDefaultTestScenario, ResourcePool, GenerateDefaultTestScenarioByDependency } from './ScenarioTool' import { timingSafeEqual } from "crypto"; @@ -146,9 +146,22 @@ export class CodeModelCliImpl implements CodeModelAz { } } if (this.SelectFirstMethod()) { + let id_groups = new Map(); + id_groups = parseResourceId(this.Request.protocol.http.path); + if (this.SelectFirstMethodParameter()) { do { let parameters = this.MethodParameter; + let defaultName = parameters.language['cli']['cliKey']; + let defaultToMatch = '{' + defaultName + '}'; + + if(!isNullOrUndefined(id_groups)) { + for(let k of id_groups.entries()) { + if(k[1] == defaultToMatch && defaultName != 'resourceGroupName') { + this.MethodParameter.language['az']['id_part'] = k[0]; + } + } + } if (parameters.language['cli'].required) { this.MethodParameter['RequiredByMethod'] = true; } else { @@ -882,6 +895,10 @@ export class CodeModelCliImpl implements CodeModelAz { return this.Parameter_NameAz(this.MethodParameter); } + public get MethodParameter_IdPart(): string { + return this.MethodParameter.language['az']['id_part']; + } + public get MethodParameter_IsArray(): boolean { if (this.submethodparameters != null) { return this.submethodparameters[this.currentSubOptionIndex].schema?.type == SchemaType.Array; diff --git a/src/plugins/azgenerator/TemplateAzureCliParams.ts b/src/plugins/azgenerator/TemplateAzureCliParams.ts index 91fe36456..c3461f280 100644 --- a/src/plugins/azgenerator/TemplateAzureCliParams.ts +++ b/src/plugins/azgenerator/TemplateAzureCliParams.ts @@ -318,7 +318,12 @@ function getCommandBody(model: CodeModelAz, needUpdate: boolean = false, needGen argument += ", arg_group='" + Capitalize(ToCamelCase(model.Parameter_MapsTo(baseParam))) + "'"; } } - + if(!model.Method_NameAz.startsWith('list') && !model.Method_NameAz.split(' ').last.startsWith('create') || needUpdate) { + if(!isNullOrUndefined(model.MethodParameter_IdPart)) { + argument += ", id_part='" + model.MethodParameter_IdPart + "'"; + } + } + argument += ")"; ToMultiLine(argument, output_args); diff --git a/src/plugins/aznamer.ts b/src/plugins/aznamer.ts index 385227458..f927dfe01 100644 --- a/src/plugins/aznamer.ts +++ b/src/plugins/aznamer.ts @@ -72,7 +72,10 @@ export class AzNamer { obj.language['az']['name'] = obj.language['cli']? obj.language['cli']['name']: obj.language['python']['name']; obj.language['az']['name'] = changeCamelToDash(obj.language['az']['name']); obj.language['az']['mapsto'] = obj.language['az']['name'].replace(/-/g, '_'); - obj.language['az']['description'] = obj.language['cli']? obj.language['cli']['description']: obj.language['python']['description'];; + obj.language['az']['description'] = obj.language['cli']? obj.language['cli']['description']: obj.language['python']['description']; + if(!isNullOrUndefined(obj.language['cli']['id_part'])) { + obj.language['az']['id_part'] = obj.language['cli']['id_part']; + } } processGlobalParam() { @@ -165,7 +168,7 @@ export class AzNamer { }); operation.requests.forEach(request => { let operationName = ""; - if(operation.language['cli'] != undefined) { + if(!isNullOrUndefined(operation.language['cli'])) { operation.language['az'] = new Language(); let commandName = this.methodMap(operation.language['cli']['name'], request.protocol.http.method); operation.language['az']['name'] = commandName; diff --git a/src/test/scenarios/attestation/output/src/attestation/azext_attestation/generated/_params.py b/src/test/scenarios/attestation/output/src/attestation/azext_attestation/generated/_params.py index c3fd2210f..cd1b5218a 100644 --- a/src/test/scenarios/attestation/output/src/attestation/azext_attestation/generated/_params.py +++ b/src/test/scenarios/attestation/output/src/attestation/azext_attestation/generated/_params.py @@ -41,16 +41,16 @@ def load_arguments(self, _): with self.argument_context('attestation attestation-provider show') as c: c.argument('resource_group_name', resource_group_name_type) - c.argument('provider_name', help='Name of the attestation service instance') + c.argument('provider_name', help='Name of the attestation service instance', id_part='name') with self.argument_context('attestation attestation-provider update') as c: c.argument('resource_group_name', resource_group_name_type) - c.argument('provider_name', help='Name of the attestation service') + c.argument('provider_name', help='Name of the attestation service', id_part='name') c.argument('tags', tags_type) with self.argument_context('attestation attestation-provider delete') as c: c.argument('resource_group_name', resource_group_name_type) - c.argument('provider_name', help='Name of the attestation service') + c.argument('provider_name', help='Name of the attestation service', id_part='name') with self.argument_context('attestation attestation-provider list-attestation') as c: c.argument('resource_group_name', resource_group_name_type) diff --git a/src/test/scenarios/datafactory/output/src/datafactory/azext_datafactory/generated/_params.py b/src/test/scenarios/datafactory/output/src/datafactory/azext_datafactory/generated/_params.py index 6a8698d9e..456f475b1 100644 --- a/src/test/scenarios/datafactory/output/src/datafactory/azext_datafactory/generated/_params.py +++ b/src/test/scenarios/datafactory/output/src/datafactory/azext_datafactory/generated/_params.py @@ -32,7 +32,7 @@ def load_arguments(self, _): with self.argument_context('datafactory show') as c: c.argument('resource_group_name', resource_group_name_type) - c.argument('factory_name', options_list=['--name', '-n'], help='The factory name.') + c.argument('factory_name', options_list=['--name', '-n'], help='The factory name.', id_part='name') c.argument('if_none_match', help='ETag of the factory entity. Should only be specified for get. If the ETag mat' 'ches the existing entity tag, or if * was provided, then no content will be returned.') @@ -59,17 +59,17 @@ def load_arguments(self, _): with self.argument_context('datafactory update') as c: c.argument('resource_group_name', resource_group_name_type) - c.argument('factory_name', options_list=['--name', '-n'], help='The factory name.') + c.argument('factory_name', options_list=['--name', '-n'], help='The factory name.', id_part='name') c.argument('tags', tags_type) c.argument('identity', action=AddIdentity, nargs='+', help='Managed service identity of the factory. Expect val' 'ue: KEY1=VALUE1 KEY2=VALUE2 ...') with self.argument_context('datafactory delete') as c: c.argument('resource_group_name', resource_group_name_type) - c.argument('factory_name', options_list=['--name', '-n'], help='The factory name.') + c.argument('factory_name', options_list=['--name', '-n'], help='The factory name.', id_part='name') with self.argument_context('datafactory configure-factory-repo') as c: - c.argument('location_id', help='The location identifier.') + c.argument('location_id', help='The location identifier.', id_part='name') c.argument('factory_resource_id', help='The factory resource id.') c.argument('factory_vsts_configuration', action=AddFactoryVstsConfiguration, nargs='+', help='Factory\'s VSTS r' 'epo information. Expect value: KEY1=VALUE1 KEY2=VALUE2 ... , available KEYs are: project-name, tena' @@ -82,7 +82,7 @@ def load_arguments(self, _): with self.argument_context('datafactory get-data-plane-access') as c: c.argument('resource_group_name', resource_group_name_type) - c.argument('factory_name', options_list=['--name', '-n'], help='The factory name.') + c.argument('factory_name', options_list=['--name', '-n'], help='The factory name.', id_part='name') c.argument('permissions', help='The string with permissions for Data Plane access. Currently only \'r\' is supp' 'orted which grants read only access.') c.argument('access_resource_path', help='The resource path to get access relative to factory. Currently only em' @@ -95,7 +95,7 @@ def load_arguments(self, _): with self.argument_context('datafactory get-git-hub-access-token') as c: c.argument('resource_group_name', resource_group_name_type) - c.argument('factory_name', options_list=['--name', '-n'], help='The factory name.') + c.argument('factory_name', options_list=['--name', '-n'], help='The factory name.', id_part='name') c.argument('git_hub_access_code', help='GitHub access code.') c.argument('git_hub_client_id', help='GitHub application client ID.') c.argument('git_hub_access_token_base_url', help='GitHub access token base URL.') diff --git a/src/test/scenarios/managed-network/output/src/managed-network/azext_managed_network/generated/_params.py b/src/test/scenarios/managed-network/output/src/managed-network/azext_managed_network/generated/_params.py index d8475c9b0..43d3d26e9 100644 --- a/src/test/scenarios/managed-network/output/src/managed-network/azext_managed_network/generated/_params.py +++ b/src/test/scenarios/managed-network/output/src/managed-network/azext_managed_network/generated/_params.py @@ -38,7 +38,8 @@ def load_arguments(self, _): with self.argument_context('managed-network mn show') as c: c.argument('resource_group_name', resource_group_name_type) - c.argument('managed_network_name', options_list=['--name', '-n'], help='The name of the Managed Network.') + c.argument('managed_network_name', options_list=['--name', '-n'], help='The name of the Managed Network.', + id_part='name') with self.argument_context('managed-network mn create') as c: c.argument('resource_group_name', resource_group_name_type) @@ -51,12 +52,14 @@ def load_arguments(self, _): with self.argument_context('managed-network mn update') as c: c.argument('resource_group_name', resource_group_name_type) - c.argument('managed_network_name', options_list=['--name', '-n'], help='The name of the Managed Network.') + c.argument('managed_network_name', options_list=['--name', '-n'], help='The name of the Managed Network.', + id_part='name') c.argument('tags', tags_type) with self.argument_context('managed-network mn delete') as c: c.argument('resource_group_name', resource_group_name_type) - c.argument('managed_network_name', options_list=['--name', '-n'], help='The name of the Managed Network.') + c.argument('managed_network_name', options_list=['--name', '-n'], help='The name of the Managed Network.', + id_part='name') with self.argument_context('managed-network mn scope-assignment list') as c: c.argument('scope', help='The base resource of the scope assignment.') @@ -105,8 +108,8 @@ def load_arguments(self, _): with self.argument_context('managed-network mn group show') as c: c.argument('resource_group_name', resource_group_name_type) - c.argument('managed_network_name', help='The name of the Managed Network.') - c.argument('group_name', help='The name of the Managed Network Group.') + c.argument('managed_network_name', help='The name of the Managed Network.', id_part='name') + c.argument('group_name', help='The name of the Managed Network Group.', id_part='child_name_1') with self.argument_context('managed-network mn group create') as c: c.argument('resource_group_name', resource_group_name_type) @@ -125,8 +128,8 @@ def load_arguments(self, _): with self.argument_context('managed-network mn group update') as c: c.argument('resource_group_name', resource_group_name_type) - c.argument('managed_network_name', help='The name of the Managed Network.') - c.argument('group_name', help='The name of the Managed Network Group.') + c.argument('managed_network_name', help='The name of the Managed Network.', id_part='name') + c.argument('group_name', help='The name of the Managed Network Group.', id_part='child_name_1') c.argument('location', arg_type=get_location_type(self.cli_ctx), validator=get_default_location_from_resource_group) c.argument('management_groups', arg_type=CLIArgumentType(options_list=['--management-groups'], help='The collec' @@ -140,8 +143,8 @@ def load_arguments(self, _): with self.argument_context('managed-network mn group delete') as c: c.argument('resource_group_name', resource_group_name_type) - c.argument('managed_network_name', help='The name of the Managed Network.') - c.argument('group_name', help='The name of the Managed Network Group.') + c.argument('managed_network_name', help='The name of the Managed Network.', id_part='name') + c.argument('group_name', help='The name of the Managed Network Group.', id_part='child_name_1') with self.argument_context('managed-network managed-network-peering-policy list') as c: c.argument('resource_group_name', resource_group_name_type) @@ -153,8 +156,8 @@ def load_arguments(self, _): with self.argument_context('managed-network managed-network-peering-policy show') as c: c.argument('resource_group_name', resource_group_name_type) - c.argument('managed_network_name', help='The name of the Managed Network.') - c.argument('policy_name', help='The name of the Managed Network Peering Policy.') + c.argument('managed_network_name', help='The name of the Managed Network.', id_part='name') + c.argument('policy_name', help='The name of the Managed Network Peering Policy.', id_part='child_name_1') with self.argument_context('managed-network managed-network-peering-policy hub-and-spoke-topology create') as c: c.argument('resource_group_name', resource_group_name_type) @@ -170,8 +173,8 @@ def load_arguments(self, _): with self.argument_context('managed-network managed-network-peering-policy hub-and-spoke-topology update') as c: c.argument('resource_group_name', resource_group_name_type) - c.argument('managed_network_name', help='The name of the Managed Network.') - c.argument('policy_name', help='The name of the Managed Network Peering Policy.') + c.argument('managed_network_name', help='The name of the Managed Network.', id_part='name') + c.argument('policy_name', help='The name of the Managed Network Peering Policy.', id_part='child_name_1') c.argument('location', arg_type=get_location_type(self.cli_ctx), validator=get_default_location_from_resource_group) c.argument('hub', action=AddHub, nargs='+', @@ -195,8 +198,8 @@ def load_arguments(self, _): with self.argument_context('managed-network managed-network-peering-policy mesh-topology update') as c: c.argument('resource_group_name', resource_group_name_type) - c.argument('managed_network_name', help='The name of the Managed Network.') - c.argument('policy_name', help='The name of the Managed Network Peering Policy.') + c.argument('managed_network_name', help='The name of the Managed Network.', id_part='name') + c.argument('policy_name', help='The name of the Managed Network Peering Policy.', id_part='child_name_1') c.argument('location', arg_type=get_location_type(self.cli_ctx), validator=get_default_location_from_resource_group) c.argument('hub', action=AddHub, nargs='+', @@ -208,5 +211,5 @@ def load_arguments(self, _): with self.argument_context('managed-network managed-network-peering-policy delete') as c: c.argument('resource_group_name', resource_group_name_type) - c.argument('managed_network_name', help='The name of the Managed Network.') - c.argument('policy_name', help='The name of the Managed Network Peering Policy.') + c.argument('managed_network_name', help='The name of the Managed Network.', id_part='name') + c.argument('policy_name', help='The name of the Managed Network Peering Policy.', id_part='child_name_1') diff --git a/src/utils/helper.ts b/src/utils/helper.ts index 88f30869c..868fb8b5a 100644 --- a/src/utils/helper.ts +++ b/src/utils/helper.ts @@ -214,4 +214,33 @@ export function ToMultiLine(sentence: string, output: string[] = undefined, maxL for (let line of ret) output.push(line); } return ret; +} + + +export function parseResourceId(mpath: string): Map { + let baseRegex: RegExp = /\/subscriptions\/(?[^\/]*)(\/resourceGroups\/(?[^\/]*))?(\/providers\/(?[^\/]*)\/(?[^\/]*)\/(?[^\/]*)(?.*))?/g; + let childRegex: RegExp = /(\/providers\/(?[^\/]*))?\/(?[^\/]*)\/(?[^\/]*)/g; + let mp: RegExpExecArray = baseRegex.exec(mpath); + let ret: Map = new Map(); + if (mp) { + let groups = mp.groups; + ret.set('subscription', groups['subscription']); + ret.set('resource_group', groups['resource_group']); + ret.set('namespace', groups['namespace']); + ret.set('type', groups['type']); + ret.set('name', groups['name']); + ret.set('children', groups['children']); + let children: RegExpExecArray = null; + let count = 0; + let childStr: string = groups["children"]; + let result = null; + while (result = childRegex.exec(childStr)) { + count++; + for(let key of ['child_namespace', 'child_type', 'child_name']) { + ret.set(key + "_" + count, result["groups"][key]); + } + } + ret.set("last_child_num", "" + count); + } + return ret; } \ No newline at end of file