* for configurable test preparers

decorator

forInstance

fix

gen preparers

multiline fix

refactor

output

multiline

subnet

multiline

minor fix

dictionary output

findresource by className and objectName

test-unique-resource

check delete httpmethod

test-unique-resource

for testResource in swagger

resume multiline

integrate oav

clear oldstyle preparer codes

esLint

work around autorest linux file:/// bug

oav@2.2.0

clean code

support split in scenario

fix

npm test

WIP

test case

test

* remove runLintball

* oav 2.2.0

* debug

* revert temp debug

* debug mac

* check mac os

* initTest in unittest

* format preparers.py

* clean

* refactor

* test-unique-resource doc

* refactor
This commit is contained in:
changlong-liu 2021-02-24 16:27:09 +08:00 коммит произвёл GitHub
Родитель 6178150352
Коммит 05501e01bc
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
37 изменённых файлов: 1090 добавлений и 656 удалений

Просмотреть файл

@ -459,6 +459,9 @@ require:
- ./readme.cli.md
- $(this-folder)/readme.az.common.md
try-require:
- ./readme.test.md
pipeline-model: v3
scope-clicommon:

Просмотреть файл

@ -404,4 +404,15 @@ You can ask autorest.az to generate minimal tests (using only required parameter
az:
...
gen-min-test: true
~~~
## How to merge resource names in example files
In some RPs the resource names in example files is not well defined. For instance: every example file use a different resource group name. This will generate many resource groups in test files.
Below flag can require test codegen to use only one resource name for each resource type.
~~~
az:
...
test-unique-resource: true
~~~

Просмотреть файл

@ -71,6 +71,7 @@
"jszip-sync": "^3.2.1-sync",
"node-yaml": "^3.2.0",
"nunjucks": "^3.2.2",
"oav": "2.2.0",
"prettier": "^2.2.1",
"request": "^2.87.0",
"request-promise-native": "1.0.8",

Просмотреть файл

@ -32,6 +32,43 @@ cli:
cli-flatten-payload: true
cli-flatten-schema: false
cli-flatten-all-overwrite-swagger: false
az:
preparers:
virtualNetworks:
abbr: vn
alias:
- virtualnetwork
create:
- az network vnet create --resource-group {resourceGroups} --name {name}
delete:
- az network vnet delete --resource-group {resourceGroups} --name {name}
subnets:
alias:
- subnet
create: |-
az network vnet subnet create -n {name} --vnet-name {virtualNetworks} -g {resourceGroups} --address-prefixes "10.0.0.0/21"
delete: |-
az network vnet subnet delete --name {name} --resource-group {resourceGroups} --vnet-name {virtualNetworks}
serviceEndpointPolicies:
abbr: sep
alias:
- serviceendpointpolicy
create: |-
az network service-endpoint policy create --name {name} --resource-group {resourceGroups}
delete: |-
az network service-endpoint policy delete --name {name} -g {resourceGroups}
networkInterfaces:
abbr: nic
alias:
- virtualinterface
create:
- az network nic create --resource-group {resourceGroups} --name {name} --vnet-name {virtualNetworks} --subnet {subnets}
delete:
- az network nic delete --resource-group {resourceGroups} --name {name}
```
``` yaml $(python) && ($(generate-sdk) == 'yes' || ($(target-mode) != 'core' && !$(generate-sdk)))

Просмотреть файл

@ -2,6 +2,7 @@ import { Host } from '@autorest/extension-base';
import { AzConfiguration, CodeGenConstants, PathConstants } from './utils/models';
import * as path from 'path';
import { runPython3 } from './python/setup';
import { NeedPreparers } from './generate/renders/tests/CliTestStep';
export class AzLinter {
async process(fileName: string): Promise<void> {
@ -22,6 +23,18 @@ export async function processRequest(host: Host): Promise<void> {
);
const azLinter = new AzLinter();
await azLinter.process(fileName);
if (NeedPreparers().size > 0) {
await azLinter.process(
path.join(
folder,
azextFolder,
PathConstants.testFolder,
PathConstants.latestFolder,
PathConstants.preparersFile,
),
);
}
} catch (error) {
console.error(`${__filename} - FAILURE ${JSON.stringify(error)} ${error.stack}`);
throw error;

Просмотреть файл

@ -1,4 +1,4 @@
/* ---------------------------------------------------------------------------------------------
/* ---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*-------------------------------------------------------------------------------------------- */
@ -6,6 +6,7 @@
import { Operation, OperationGroup, Parameter, Property, Schema } from '@azure-tools/codemodel';
import { CodeModelTypes, DataGraph, GenerationMode, RenderInput } from '../utils/models';
import { ResourcePool } from './renders/tests/ScenarioTool';
import { TestStepExampleFileRestCall } from 'oav/dist/lib/testScenario/testResourceTypes';
export class MethodParam {
public value: any;
@ -254,7 +255,13 @@ export interface CodeModelAz {
GenerateTestInit(): void;
SelectFirstExample(): boolean;
SelectNextExample(): boolean;
FindExampleById(id: string, commandParams: any, examples: any[], minimum: boolean): string[][];
FindExampleById(
id: string,
commandParams: any,
examples: any[],
minimum: boolean,
step?: TestStepExampleFileRestCall,
): string[][];
SelectFirstAzExample(): boolean;
SelectNextAzExample(): boolean;
AzExample: CommandExample;
@ -264,7 +271,7 @@ export interface CodeModelAz {
GetSubscriptionKey(): string;
GetPreparerEntities(): any[];
GatherInternalResource();
FindExampleWaitById(id: string): string[][];
FindExampleWaitById(id: string, step?: TestStepExampleFileRestCall): string[][];
GetExampleItems(example: CommandExample, isTest: boolean, commandParams: any): string[];
GetExampleChecks(example: CommandExample): string[];
RandomizeNames: boolean;
@ -278,4 +285,5 @@ export interface CodeModelAz {
inputProperties: Map<CodeModelTypes, RenderInput>,
dependencies: DataGraph,
);
GetTestUniqueResource: boolean;
}

Просмотреть файл

@ -1,4 +1,4 @@
/* ---------------------------------------------------------------------------------------------
/* ---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*-------------------------------------------------------------------------------------------- */
@ -58,9 +58,11 @@ import {
ResourcePool,
ObjectStatus,
GroupTestScenario,
LoadPreparesConfig,
} from './renders/tests/ScenarioTool';
import { readFile } from '@azure-tools/async-io';
import { TestStepExampleFileRestCall } from 'oav/dist/lib/testScenario/testResourceTypes';
import * as process from 'process';
class ActionParam {
public constructor(
public groupOpActionName: string,
@ -126,6 +128,7 @@ export class CodeModelCliImpl implements CodeModelAz {
this._clientAuthenticationPolicy = this.options[
CodeGenConstants.clientAuthenticationPolicy
];
LoadPreparesConfig(this.options[CodeGenConstants.preparers]);
// this.sortOperationByAzCommand();
}
@ -138,8 +141,6 @@ export class CodeModelCliImpl implements CodeModelAz {
this.sortOperationByAzCommand();
this.calcOptionRequiredByMethod();
this.dealingParameterAlias();
this.GenerateTestInit();
this.GetAllExamples();
}
private sortOperationByAzCommand() {
@ -207,6 +208,12 @@ export class CodeModelCliImpl implements CodeModelAz {
return true;
}
public get GetTestUniqueResource(): boolean {
const ret = this.options?.[CodeGenConstants.testUniqueResource];
if (ret) return true;
return false;
}
public get GenMinTest(): boolean {
const genMinTest = this.options?.['gen-min-test'];
if (genMinTest) return true;
@ -228,7 +235,10 @@ export class CodeModelCliImpl implements CodeModelAz {
v.indexOf('specification') > 0
) {
const p = v.indexOf('specification');
return v.slice('file:///'.length, p - 1);
if (process.platform.toLowerCase().startsWith('win')) {
return v.slice('file:///'.length, p - 1);
}
return v.slice('file:///'.length - 1, p - 1);
}
}
return undefined;
@ -772,15 +782,13 @@ export class CodeModelCliImpl implements CodeModelAz {
//= ================================================================================================================
public GenerateTestInit(): void {
if (this.codeModel['test-scenario']) {
// if ('examples' in this.codeModel['test-scenario']) {
// //new style of example configuration
// this._testScenario = this.codeModel['test-scenario']['examples'];
// }
// else {
// //old style of example configuration
// this._testScenario = this.codeModel['test-scenario']
// }
if (this.GetResourcePool().hasTestResourceScenario) {
this._testScenario = GroupTestScenario(
this.GetResourcePool().generateTestScenario(),
this.Extension_NameUnderscored,
);
this._configuredScenario = true;
} else if (this.codeModel['test-scenario']) {
this._testScenario = GroupTestScenario(
this.codeModel['test-scenario'],
this.Extension_NameUnderscored,
@ -791,6 +799,7 @@ export class CodeModelCliImpl implements CodeModelAz {
this._configuredScenario = false;
}
this.GatherInternalResource();
this.GetAllExamples();
}
public get ConfiguredScenario(): boolean {
@ -3039,6 +3048,32 @@ export class CodeModelCliImpl implements CodeModelAz {
if (!isNullOrUndefined(this.Method_AzExamples) && this.Method_AzExamples.length > 0) {
return this.Method_AzExamples;
}
const examples: CommandExample[] = [];
if (this.Examples) {
Object.entries(this.Examples).forEach(([id, exampleObj]) => {
const example = this.CreateCommandExample(id, exampleObj);
if (!isNullOrUndefined(example)) examples.push(example);
});
}
this.Method_AzExamples = examples;
return examples;
}
public GetExampleById(id: string, exampleObj: any): CommandExample {
let ret: CommandExample = undefined;
if (this.Examples) {
Object.entries(this.Examples).forEach(([_id, _exampleObj]) => {
if (!isNullOrUndefined(ret)) return;
if (!isNullOrUndefined(id) && id.toLowerCase() !== _id.toLowerCase()) return;
if (!isNullOrUndefined(exampleObj)) _exampleObj = exampleObj;
const example = this.CreateCommandExample(_id, _exampleObj);
if (!isNullOrUndefined(example)) ret = example;
});
}
return ret;
}
public CreateCommandExample(id: string, exampleObj: any): CommandExample {
function forUpdate(model: CodeModelCliImpl, exampleName: string): boolean {
const lowercase: string = exampleName.toLowerCase();
return (
@ -3049,61 +3084,51 @@ export class CodeModelCliImpl implements CodeModelAz {
);
}
const examples: CommandExample[] = [];
if (this.Examples) {
Object.entries(this.Examples).forEach(([id, exampleObj]) => {
const example = new CommandExample();
example.Method = this.Command_MethodName;
example.Id = `/${this.CommandGroup_Key}/${this.Method_HttpMethod}/${id}`;
example.Title = exampleObj.title || id;
example.Path = this.Method_Path;
example.HttpMethod = this.Method_HttpMethod;
example.ResourceClassName = this.CommandGroup_Key;
const params = this.GetExampleParameters(exampleObj);
example.Parameters = this.ConvertToCliParameters(params);
example.MethodResponses = this.Method.responses || [];
example.Method_IsLongRun = !!this.Method.extensions?.[
'x-ms-long-running-operation'
];
example.ExampleObj = exampleObj;
if (this.Method_GetSplitOriginalOperation) {
// filter example by name for generic createorupdate
if (
this.Command_MethodName.toLowerCase() === 'update' &&
!forUpdate(this, id)
) {
return;
}
if (this.Command_MethodName.toLowerCase() !== 'update' && forUpdate(this, id)) {
return;
}
}
if (this.filterExampleByPoly(exampleObj, example)) {
for (let i = 0; i < example.Parameters.length; i++) {
if (this.isDiscriminator(example.Parameters[i].methodParam.value)) {
example.Parameters.splice(i, 1);
i--;
}
}
examples.push(example);
}
example.commandStringItems = this.GetExampleItems(example, false, undefined);
example.CommandString = example.commandStringItems.join(' ');
example.WaitCommandString = this.GetExampleWait(example).join(' ');
});
const example = new CommandExample();
example.Method = this.Command_MethodName;
example.Id = `/${this.CommandGroup_Key}/${this.Method_HttpMethod}/${id}`;
example.Title = exampleObj.title || id;
example.Path = this.Method_Path;
example.HttpMethod = this.Method_HttpMethod;
example.ResourceClassName = this.CommandGroup_Key;
const params = this.GetExampleParameters(exampleObj);
example.Parameters = this.ConvertToCliParameters(params);
example.MethodResponses = this.Method.responses || [];
example.Method_IsLongRun = !!this.Method.extensions?.['x-ms-long-running-operation'];
example.ExampleObj = exampleObj;
if (this.Method_GetSplitOriginalOperation) {
// filter example by name for generic createorupdate
if (this.Command_MethodName.toLowerCase() === 'update' && !forUpdate(this, id)) {
return;
}
if (this.Command_MethodName.toLowerCase() !== 'update' && forUpdate(this, id)) {
return;
}
}
this.Method_AzExamples = examples;
return examples;
if (this.filterExampleByPoly(exampleObj, example)) {
for (let i = 0; i < example.Parameters.length; i++) {
if (this.isDiscriminator(example.Parameters[i].methodParam.value)) {
example.Parameters.splice(i, 1);
i--;
}
}
example.commandStringItems = this.GetExampleItems(example, false, undefined);
example.CommandString = example.commandStringItems.join(' ');
example.WaitCommandString = this.GetExampleWait(example).join(' ');
return example;
}
return undefined;
}
public GetExampleChecks(example: CommandExample): string[] {
const ret: string[] = [];
if (!this.GenChecks) return ret;
let resourceObjectName;
let resourceObjectName = undefined;
for (const param of example.Parameters) {
if (
example.ResourceClassName &&
this.resourcePool.isResource(param.defaultName) === example.ResourceClassName
this.resourcePool.isResource(param.defaultName, param.rawValue) ===
example.ResourceClassName
) {
resourceObjectName = param.value;
}
@ -3137,21 +3162,21 @@ export class CodeModelCliImpl implements CodeModelAz {
continue;
let paramValue = param.value;
if (isTest || this.FormalizeNames) {
let replacedValue = this.resourcePool.addEndpointResource(
let replacedValue = this.resourcePool.addParamResource(
param.defaultName,
paramValue,
param.isJson,
param.keyValue,
[],
[],
param,
isTest,
);
if (replacedValue === paramValue) {
replacedValue = this.resourcePool.addParamResource(
param.defaultName,
replacedValue = this.resourcePool.addEndpointResource(
paramValue,
param.isJson,
param.keyValue,
[],
[],
param,
isTest,
);
}
@ -3170,7 +3195,8 @@ export class CodeModelCliImpl implements CodeModelAz {
if (
example.ResourceClassName &&
this.resourcePool.isResource(param.defaultName) === example.ResourceClassName
this.resourcePool.isResource(param.defaultName, param.rawValue) ===
example.ResourceClassName
) {
resourceObjectName = param.value;
}
@ -3236,23 +3262,24 @@ export class CodeModelCliImpl implements CodeModelAz {
const paramKey = param.methodParam.value.language?.['cli']?.cliKey;
if (
paramKey === 'resourceGroupName' ||
this.resourcePool.isResource(paramKey) === example.ResourceClassName
this.resourcePool.isResource(paramKey, param.rawValue) ===
example.ResourceClassName
) {
let paramValue = param.value;
let replacedValue = this.resourcePool.addEndpointResource(
let replacedValue = this.resourcePool.addParamResource(
param.defaultName,
paramValue,
param.isJson,
param.keyValue,
[],
[],
param,
);
if (replacedValue === paramValue) {
replacedValue = this.resourcePool.addParamResource(
param.defaultName,
replacedValue = this.resourcePool.addEndpointResource(
paramValue,
param.isJson,
param.keyValue,
[],
[],
param,
);
}
paramValue = replacedValue;
@ -3262,7 +3289,10 @@ export class CodeModelCliImpl implements CodeModelAz {
}
parameters.push(param.name + ' ' + slp);
}
if (this.resourcePool.isResource(paramKey) === example.ResourceClassName)
if (
this.resourcePool.isResource(paramKey, param.rawValue) ===
example.ResourceClassName
)
foundResource = true;
}
}
@ -3286,21 +3316,33 @@ export class CodeModelCliImpl implements CodeModelAz {
commandParams: any,
examples: CommandExample[],
minimum = false,
step: TestStepExampleFileRestCall = undefined,
): string[][] {
const ret: string[][] = [];
this.GetAllExamples(id, (example) => {
examples.push(example);
ret.push(this.GetExampleItems(example, true, commandParams, minimum));
});
this.GetAllExamples(
id,
(example) => {
examples.push(example);
ret.push(this.GetExampleItems(example, true, commandParams, minimum));
},
step?.exampleTemplate,
);
return ret;
}
public FindExampleWaitById(id: string): string[][] {
public FindExampleWaitById(
id: string,
step: TestStepExampleFileRestCall = undefined,
): string[][] {
const ret: string[][] = [];
this.GetAllExamples(id, (example) => {
const waitCmd = this.GetExampleWait(example);
if (waitCmd.length > 0) ret.push(waitCmd);
});
this.GetAllExamples(
id,
(example) => {
const waitCmd = this.GetExampleWait(example);
if (waitCmd.length > 0) ret.push(waitCmd);
},
step?.exampleTemplate,
);
return ret;
}
@ -3366,7 +3408,7 @@ export class CodeModelCliImpl implements CodeModelAz {
this.MethodParameter?.schema?.type !== 'constant'
) {
const paramName = this.MethodParameter.language['cli'].cliKey;
const onResource = this.resourcePool.isResource(paramName);
const onResource = this.resourcePool.isResource(paramName, undefined);
for (const example of examples) {
for (const param of example.Parameters) {
if (
@ -3550,12 +3592,24 @@ export class CodeModelCliImpl implements CodeModelAz {
);
}
public GetAllExamples(id?: string, callback?: (example) => void): CommandExample[] {
public GetAllExamples(
id?: string,
callback?: (example) => void,
exampleTemplate?: any,
): CommandExample[] {
const ret: CommandExample[] = [];
let found = false;
this.GetAllMethods(null, () => {
if (found) return;
for (const example of this.GetExamples()) {
let examples: CommandExample[];
if (!isNullOrUndefined(exampleTemplate)) {
const example = this.GetExampleById(id, exampleTemplate);
if (isNullOrUndefined(example)) return;
examples = [example];
} else {
examples = this.GetExamples();
}
for (const example of examples) {
if (id && !this.matchExample(example, id)) continue;
if (callback) {
callback(example);

Просмотреть файл

@ -31,6 +31,8 @@ export async function processRequest(host: Host) {
}
openInplaceGen();
await model.resourcePool.loadTestResources();
model.GenerateTestInit();
const generator = AzGeneratorFactory.createAzGenerator(model);
await generator.generateAll();
const files = generator.files;

Просмотреть файл

@ -34,6 +34,9 @@ export abstract class GeneratorBase {
!fs.existsSync(path.join(this.model.azOutputFolder, template.relativePath))
) {
const genContent = await template.fullGeneration();
if (template.skip) {
return;
}
if (inplace) {
this.files[template.relativePath] = inplaceGen(
this.model.azOutputFolder,
@ -57,6 +60,9 @@ export abstract class GeneratorBase {
.toString();
}
const genContent = await template.incrementalGeneration(base);
if (template.skip) {
return;
}
if (inplace) {
this.files[template.relativePath] = inplaceGen(
this.model.azOutputFolder,

Просмотреть файл

@ -20,7 +20,7 @@ import { GenerateAzureCliValidators } from '../renders/generated/CliValidators';
import { CliTestInit } from '../renders/tests/CliTestInit';
import { CliTestPrepare } from '../renders/tests/CliTestPrepare';
import { CliTestScenario } from '../renders/tests/CliTestScenario';
import { CliTestStep, NeedPreparer } from '../renders/tests/CliTestStep';
import { CliTestStep, NeedPreparers } from '../renders/tests/CliTestStep';
import { GenerateMetaFile } from '../renders/CliMeta';
export class AzCoreFullGenerator extends GeneratorBase {
constructor(model: CodeModelAz) {
@ -103,9 +103,22 @@ export class AzCoreFullGenerator extends GeneratorBase {
true,
);
}
if (NeedPreparer()) {
await this.generateFullSingleAndAddtoOutput(new CliTestPrepare(model));
const needPreparers = NeedPreparers();
if (needPreparers.size > 0) {
await this.generateFullSingleAndAddtoOutput(
new CliTestPrepare(model, [...needPreparers]),
);
}
model
.GetResourcePool()
.generateArmTemplate(
files,
path.join(
model.azOutputFolder,
PathConstants.testFolder,
PathConstants.latestFolder,
),
);
GenerateMetaFile(model);
} while (model.SelectNextExtension());
}

Просмотреть файл

@ -25,7 +25,7 @@ import { GenerateAzureCliValidators } from '../renders/generated/CliValidators';
import { CliTestInit } from '../renders/tests/CliTestInit';
import { CliTestPrepare } from '../renders/tests/CliTestPrepare';
import { CliTestScenario } from '../renders/tests/CliTestScenario';
import { CliTestStep, NeedPreparer } from '../renders/tests/CliTestStep';
import { CliTestStep, NeedPreparers } from '../renders/tests/CliTestStep';
import { GenerateMetaFile } from '../renders/CliMeta';
import { CliExtSetupPy } from '../renders/extraExt/CliExtSetupPy';
@ -145,9 +145,22 @@ export class AzCoreIncrementalGenerator extends GeneratorBase {
true,
);
}
if (NeedPreparer()) {
await this.generateIncrementalSingleAndAddtoOutput(new CliTestPrepare(this.model));
const needPreparers = NeedPreparers();
if (needPreparers.size > 0) {
await this.generateIncrementalSingleAndAddtoOutput(
new CliTestPrepare(this.model, [...needPreparers]),
);
}
this.model
.GetResourcePool()
.generateArmTemplate(
this.files,
path.join(
this.model.azOutputFolder,
PathConstants.testFolder,
PathConstants.latestFolder,
),
);
GenerateMetaFile(this.model);
}
}

Просмотреть файл

@ -23,7 +23,7 @@ import { GenerateAzureCliValidators } from '../renders/generated/CliValidators';
import { CliTestInit } from '../renders/tests/CliTestInit';
import { CliTestPrepare } from '../renders/tests/CliTestPrepare';
import { CliTestScenario } from '../renders/tests/CliTestScenario';
import { CliTestStep, NeedPreparer } from '../renders/tests/CliTestStep';
import { CliTestStep, NeedPreparers } from '../renders/tests/CliTestStep';
import { GenerateMetaFile } from '../renders/CliMeta';
import { CliExtSetupCfg } from '../renders/extraExt/CliExtSetupCfg';
import { CliExtHistory } from '../renders/extraExt/CliExtHistory';
@ -101,9 +101,18 @@ export class AzExtensionFullGenerator extends GeneratorBase {
true,
);
}
if (NeedPreparer()) {
await this.generateFullSingleAndAddtoOutput(new CliTestPrepare(this.model));
const needPreparers = NeedPreparers();
if (needPreparers.size > 0) {
await this.generateFullSingleAndAddtoOutput(
new CliTestPrepare(this.model, [...needPreparers]),
);
}
this.model
.GetResourcePool()
.generateArmTemplate(
this.files,
path.join(this.azDirectory, PathConstants.testFolder, PathConstants.latestFolder),
);
GenerateMetaFile(this.model);
}
}

Просмотреть файл

@ -25,7 +25,7 @@ import { GenerateAzureCliValidators } from '../renders/generated/CliValidators';
import { CliTestInit } from '../renders/tests/CliTestInit';
import { CliTestPrepare } from '../renders/tests/CliTestPrepare';
import { CliTestScenario } from '../renders/tests/CliTestScenario';
import { CliTestStep, NeedPreparer } from '../renders/tests/CliTestStep';
import { CliTestStep, NeedPreparers } from '../renders/tests/CliTestStep';
import { GenerateMetaFile } from '../renders/CliMeta';
export class AzExtensionIncrementalGenerator extends GeneratorBase {
@ -132,9 +132,18 @@ export class AzExtensionIncrementalGenerator extends GeneratorBase {
true,
);
}
if (NeedPreparer()) {
await this.generateIncrementalSingleAndAddtoOutput(new CliTestPrepare(this.model));
const needPreparers = NeedPreparers();
if (needPreparers.size > 0) {
await this.generateIncrementalSingleAndAddtoOutput(
new CliTestPrepare(this.model, [...needPreparers]),
);
}
this.model
.GetResourcePool()
.generateArmTemplate(
this.files,
path.join(this.azDirectory, PathConstants.testFolder, PathConstants.latestFolder),
);
GenerateMetaFile(this.model);
}
}

Просмотреть файл

@ -11,12 +11,14 @@ export abstract class TemplateBase {
protected isDebugMode: boolean;
public relativePath: string;
protected tmplPath: string;
public skip: boolean;
constructor(model: CodeModelAz) {
this.model = model;
this.isDebugMode = AzConfiguration.getValue(CodeGenConstants.debug);
this.relativePath = '';
this.tmplPath = '';
this.skip = false;
}
public abstract async fullGeneration(): Promise<string[]>;

Просмотреть файл

@ -1,4 +1,4 @@
/* ---------------------------------------------------------------------------------------------
/* ---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*-------------------------------------------------------------------------------------------- */

Просмотреть файл

@ -10,15 +10,11 @@ import { PathConstants } from '../../../utils/models';
export class CliTestInit extends TemplateBase {
constructor(model: CodeModelAz) {
super(model);
if (this.model.IsCliCore) {
this.relativePath = path.join(PathConstants.testFolder, PathConstants.initFile);
} else {
this.relativePath = path.join(
model.AzextFolder,
PathConstants.testFolder,
PathConstants.initFile,
);
}
this.relativePath = path.join(
model.AzextFolder,
PathConstants.testFolder,
PathConstants.initFile,
);
this.tmplPath = path.join(PathConstants.templateRootFolder, 'tests/init.py.njx');
}

Просмотреть файл

@ -1,30 +1,43 @@
import * as path from 'path';
import { CodeModelAz } from '../../CodeModelAz';
import { HeaderGenerator } from '../Header';
import { TemplateBase } from '../TemplateBase';
import { PathConstants } from '../../../utils/models';
import { GenPreparerName, preparerInfos } from './ScenarioTool';
import { ToJsonString } from '../../../utils/helper';
class FuncData {
constructor(public cmdTemplate: string, public cmdFormats: string[]) {}
}
export class PreparerData {
public initParamPairs: [string, string][];
public attributes: string[];
public createFunc: FuncData;
public removeFunc: FuncData;
constructor(public className: string) {
this.initParamPairs = [];
this.attributes = [];
this.createFunc = new FuncData(undefined, []);
this.removeFunc = new FuncData(undefined, []);
}
}
export class CliTestPrepare extends TemplateBase {
constructor(model: CodeModelAz) {
resourceNames: string[];
constructor(model: CodeModelAz, resourceNames: string[]) {
super(model);
if (this.model.IsCliCore) {
this.relativePath = path.join(
PathConstants.testFolder,
PathConstants.latestFolder,
PathConstants.preparersFile,
);
} else {
this.relativePath = path.join(
model.AzextFolder,
PathConstants.testFolder,
PathConstants.latestFolder,
PathConstants.preparersFile,
);
}
this.resourceNames = resourceNames;
this.relativePath = path.join(
model.AzextFolder,
PathConstants.testFolder,
PathConstants.latestFolder,
PathConstants.preparersFile,
);
this.tmplPath = path.join(PathConstants.templateRootFolder, 'tests/latest/prepares.py.njx');
}
public async fullGeneration(): Promise<string[]> {
// this.GenerateAzureCliTestPrepare(this.model);
return await this.render();
}
@ -32,8 +45,77 @@ export class CliTestPrepare extends TemplateBase {
return await this.fullGeneration();
}
public async GetRenderData(model: CodeModelAz): Promise<string[]> {
const output: string[] = [];
return output;
public async GetRenderData(model: CodeModelAz): Promise<any> {
const data = {
preparers: [],
};
for (const resourceName of this.resourceNames) {
data.preparers.push(this.CreatePreparer(model, resourceName));
}
return data;
}
private CreatePreparer(model: CodeModelAz, resourceName: string) {
const preparerInfo = preparerInfos[resourceName];
const preparerData = new PreparerData(GenPreparerName(preparerInfo.className));
for (let i = 0; i < preparerInfo.dependResources.length; i++) {
preparerData.initParamPairs.push([
preparerInfos[preparerInfo.className].dependParameters[i],
ToJsonString(
preparerInfos[preparerInfos[preparerInfo.className].dependResources[i]].key,
),
]);
}
preparerData.initParamPairs.push(['key', ToJsonString(preparerInfo.key)]);
for (const k in preparerInfo.config.inits) {
preparerData.initParamPairs.push([k, ToJsonString(preparerInfo.config.inits[k])]);
}
for (const param of preparerInfo.dependParameters.concat(
Object.getOwnPropertyNames(preparerInfo.config.inits),
)) {
preparerData.attributes.push(param);
}
function genLiveRun(templates: string[], funcData: FuncData) {
for (const template of templates) {
const variables: string[] = [];
let depends: string[] = template.match(/\{.*?\}/g);
depends = depends.map((x: string) => {
return x.substr(1, x.length - 2).toLowerCase();
});
for (const depend of depends) {
if (depend == 'name') {
variables.push(`name`);
} else {
for (
let i = 0;
i < preparerInfos[preparerInfo.className].dependParameters.length;
i++
) {
if (
model
.GetResourcePool()
.isResource(
preparerInfos[preparerInfo.className].dependResources[i],
null,
) === model.GetResourcePool().isResource(depend, null)
) {
variables.push(
`self.test_class_instance.kwargs.get(self.${
preparerInfos[preparerInfo.className].dependParameters[i]
})`,
);
}
}
}
}
funcData.cmdTemplate = template.replace(/\{.*?\}/g, '{}');
funcData.cmdFormats = variables;
}
}
genLiveRun(preparerInfo.config.create, preparerData.createFunc);
genLiveRun(preparerInfo.config.delete, preparerData.removeFunc);
return preparerData;
}
}

Просмотреть файл

@ -1,4 +1,4 @@
/* ---------------------------------------------------------------------------------------------
/* ---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*-------------------------------------------------------------------------------------------- */
@ -11,32 +11,24 @@ import { TemplateBase } from '../TemplateBase';
import { CodeGenConstants, PathConstants } from '../../../utils/models';
export class CliTestScenario extends TemplateBase {
constructor(model: CodeModelAz, testFilename: string, configValue: any, groupName: string) {
super(model);
if (this.model.IsCliCore) {
this.relativePath = path.join(
PathConstants.testFolder,
PathConstants.latestFolder,
testFilename,
);
} else {
this.relativePath = path.join(
model.AzextFolder,
PathConstants.testFolder,
PathConstants.latestFolder,
testFilename,
);
}
this.configValue = configValue;
this.groupName = groupName;
}
public configValue: any;
private groupName: string;
private header: HeaderGenerator = new HeaderGenerator();
private scenarios: string[] = [];
constructor(model: CodeModelAz, testFilename: string, configValue: any, groupName: string) {
super(model);
this.relativePath = path.join(
model.AzextFolder,
PathConstants.testFolder,
PathConstants.latestFolder,
testFilename,
);
this.configValue = configValue;
this.groupName = groupName;
this.skip = true;
}
public async fullGeneration(): Promise<string[]> {
this.StartGenerateAzureCliTestScenario();
for (const scenarioName of Object.getOwnPropertyNames(this.configValue)) {
@ -109,7 +101,7 @@ export class CliTestScenario extends TemplateBase {
),
);
function buildSenario(header: HeaderGenerator, outputFunc: string[], minimum: boolean) {
function buildSenario(template: CliTestScenario, outputFunc: string[], minimum: boolean) {
model.GetResourcePool().clearExampleParams();
// go through the examples to generate steps
@ -127,6 +119,7 @@ export class CliTestScenario extends TemplateBase {
commandParams,
examples,
minimum,
config[ci].step,
)) {
exampleIdx += 1;
if (exampleCmd && exampleCmd.length > 0) {
@ -152,7 +145,7 @@ export class CliTestScenario extends TemplateBase {
!disabled &&
check.indexOf('json.loads') >= 0
) {
header.addImport('json');
template.header.addImport('json');
jsonAdded = true;
}
}
@ -169,7 +162,8 @@ export class CliTestScenario extends TemplateBase {
}
}
if (found) {
header.addFromImport('.example_steps', [functionName]);
template.header.addFromImport('.example_steps', [functionName]);
template.skip = false;
} else {
outputFunc.push(...ToMultiLine(` # STEP NOT FOUND: ${exampleId}`));
}
@ -184,7 +178,14 @@ export class CliTestScenario extends TemplateBase {
)}):`,
),
);
steps.push(' pass');
if (
functionName.startsWith('setup_') &&
model.GetResourcePool().hasTestResourceScenario
) {
steps.push(...model.GetResourcePool().setupWithArmTemplate());
} else {
steps.push(' pass');
}
steps.push('');
steps.push('');
}
@ -198,7 +199,7 @@ export class CliTestScenario extends TemplateBase {
outputFunc.push('');
outputFunc.push('');
}
buildSenario(this.header, funcScenario, false);
buildSenario(this, funcScenario, false);
if (model.GenMinTest) {
funcMinScenario.push('@try_manual');
funcMinScenario.push(
@ -208,7 +209,7 @@ export class CliTestScenario extends TemplateBase {
)}):`,
),
);
buildSenario(this.header, funcMinScenario, true);
buildSenario(this, funcMinScenario, true);
}
classInfo.push(' def __init__(self, *args, **kwargs):');
classInfo.push(` super(${testClassName}, self).__init__(*args, **kwargs)`);

Просмотреть файл

@ -1,4 +1,4 @@
/* ---------------------------------------------------------------------------------------------
/* ---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*-------------------------------------------------------------------------------------------- */
@ -10,37 +10,29 @@ import { HeaderGenerator } from '../Header';
import { TemplateBase } from '../TemplateBase';
import { CodeGenConstants, PathConstants } from '../../../utils/models';
let usePreparers: boolean, shortToLongName, funcNames, allSteps, stepBuff: any;
let usePreparers: Set<string>, shortToLongName, funcNames, allSteps, stepBuff: Record<string, any>;
function initVars() {
usePreparers = false;
usePreparers = new Set<string>();
shortToLongName = {};
funcNames = {};
allSteps = [];
stepBuff = {};
}
export function NeedPreparer(): boolean {
export function NeedPreparers(): Set<string> {
return usePreparers;
}
export class CliTestStep extends TemplateBase {
constructor(model: CodeModelAz) {
super(model);
if (this.model.IsCliCore) {
this.relativePath = path.join(
PathConstants.testFolder,
PathConstants.latestFolder,
PathConstants.testStepFile,
);
} else {
this.relativePath = path.join(
model.AzextFolder,
PathConstants.testFolder,
PathConstants.latestFolder,
PathConstants.testStepFile,
);
}
this.relativePath = path.join(
model.AzextFolder,
PathConstants.testFolder,
PathConstants.latestFolder,
PathConstants.testStepFile,
);
}
public async fullGeneration(): Promise<string[]> {
@ -61,7 +53,15 @@ export class CliTestStep extends TemplateBase {
steps.push('');
const commandParams = model.GatherInternalResource();
const config: any = deepCopy(model.Extension_DefaultTestScenario);
let config: any = [];
if (model.GetResourcePool().hasTestResourceScenario) {
for (const g in model.Extension_TestScenario) {
for (const s in model.Extension_TestScenario[g])
config.push(...model.Extension_TestScenario[g][s]);
}
} else {
config = deepCopy(model.Extension_DefaultTestScenario);
}
const header: HeaderGenerator = new HeaderGenerator();
@ -95,6 +95,7 @@ export class CliTestStep extends TemplateBase {
commandParams,
examples,
minimum,
config[ci].step,
)) {
exampleIdx += 1;
if (exampleCmd && exampleCmd.length > 0) {
@ -131,7 +132,10 @@ export class CliTestStep extends TemplateBase {
);
} else {
stepBuff[cmdString] = functionName;
if (exampleCmd[0].indexOf(' delete') > -1) {
if (
exampleCmd[0].indexOf(' delete') > -1 &&
examples[exampleIdx].HttpMethod.toLowerCase() === 'delete'
) {
exampleCmd[0] += ' -y';
}
@ -236,10 +240,13 @@ export class CliTestStep extends TemplateBase {
const parameterNames = [];
for (const entity of model.GetPreparerEntities() as PreparerEntity[]) {
if (!entity.info.name) {
const created = model.GetTestUniqueResource
? entity.info.createdObjectNames.length > 0
: entity.info.createdObjectNames.indexOf(entity.objectName) >= 0;
internalObjects.push([
entity.info.className,
getResourceKey(entity.info.className, entity.objectName),
entity.info.createdObjectNames.indexOf(entity.objectName) >= 0,
created,
entity.objectName,
]);
continue;
@ -263,13 +270,11 @@ export class CliTestStep extends TemplateBase {
line += ')';
ToMultiLine(line, decorators);
if (decorated.indexOf(entity.info.name) < 0) {
if (entity.info.name === 'ResourceGroupPreparer') {
if (!entity.info.needGen) {
header.addFromImport('azure.cli.testsdk', [entity.info.name]);
} else if (entity.info.name === 'StorageAccountPreparer') {
header.addFromImport('azure.cli.testsdk', [entity.info.name]);
} else {
} else if (entity.info.needGen) {
header.addFromImport('.preparers', [entity.info.name]);
usePreparers = true;
usePreparers.add(entity.info.className);
}
decorated.push(entity.info.name);
}

Просмотреть файл

@ -7,8 +7,21 @@ import {
changeCamelToDash,
MergeSort,
isNullOrUndefined,
Capitalize,
ToSnakeCase,
setPathValue,
checkNested,
} from '../../../utils/helper';
import { EnglishPluralizationService } from '@azure-tools/codegen';
import { AzConfiguration, CodeGenConstants } from '../../../utils/models';
import { TestResourceLoader } from 'oav/dist/lib/testScenario/testResourceLoader';
import {
TestDefinitionFile,
TestStepArmTemplateDeployment,
TestStepExampleFileRestCall,
} from 'oav/dist/lib/testScenario/testResourceTypes';
import * as path from 'path';
import * as process from 'process';
export const azOptions = {};
@ -127,8 +140,13 @@ export function GroupTestScenario(testScenario: any, extensionName: string) {
}
}
} else if (Array.isArray(testScenario)) {
let curGroup = extensionName;
for (let ci = 0; ci < testScenario.length; ci++) {
addScenario(extensionName, defaultScenario, [testScenario[ci]]);
if (Object.prototype.hasOwnProperty.call(testScenario[ci], 'split')) {
curGroup = testScenario[ci].split;
} else {
addScenario(curGroup, defaultScenario, [testScenario[ci]]);
}
}
}
@ -136,42 +154,18 @@ export function GroupTestScenario(testScenario: any, extensionName: string) {
}
const SUBSCRIPTIONS = 'subscriptions';
const RESOUREGROUP = 'resource-group';
const VIRTUALNETWORK = 'virtual-network';
const STORAGEACCOUNT = 'storage-account';
const SUBNET = 'subnet';
const NETWORKINTERFACE = 'network-interface';
const resourceClassDepends = {
[RESOUREGROUP]: [],
[VIRTUALNETWORK]: [RESOUREGROUP],
[SUBNET]: [VIRTUALNETWORK, RESOUREGROUP],
[STORAGEACCOUNT]: [RESOUREGROUP],
[NETWORKINTERFACE]: [VIRTUALNETWORK, RESOUREGROUP],
};
const resourceLanguages = {
[RESOUREGROUP]: ['resource-group', 'resourceGroupName', 'resourceGroups'],
[VIRTUALNETWORK]: ['virtual-network', 'virtualNetworkName', 'virtualNetworks'],
[SUBNET]: ['subnet', 'subnetName', 'subnets'],
[STORAGEACCOUNT]: ['storage-account', 'storageAccountName', 'storageAccounts'],
[NETWORKINTERFACE]: ['network-interface', 'networkInterfaceName', 'networkInterfaces'],
};
const resourceClassKeys = {
[RESOUREGROUP]: 'rg',
[VIRTUALNETWORK]: 'vn',
[SUBNET]: 'sn',
[STORAGEACCOUNT]: 'sa',
[NETWORKINTERFACE]: 'nic',
};
const RESOUREGROUP = 'resourceGroups';
const STORAGEACCOUNT = 'storageAccounts';
export function TopoSortResource() {
const ret = [];
const resources = Object.keys(resourceClassDepends);
// let reverse_depends = { };
const depends = deepCopy(resourceClassDepends);
while (ret.length < Object.keys(resourceClassDepends).length) {
const resources = Object.keys(preparerInfos);
//let reverse_depends = { };
const depends = {};
for (const r in preparerInfos) {
depends[r] = deepCopy(preparerInfos[r].dependResources);
}
while (ret.length < Object.keys(preparerInfos).length) {
let decreasing = false;
for (const a of resources) {
if (!isNullOrUndefined(depends[a]) && depends[a].length === 0) {
@ -199,53 +193,131 @@ export function TopoSortResource() {
return ret;
}
class PreparerInfo {
export class PreparerConfig {
resource: string;
fullType: string;
abbr: string;
alias: string[];
forInstance: string;
create: string[];
delete: string[];
inits: { [key: string]: any };
}
export class PreparerInfo {
name: string;
className: string;
dependParameters: string[];
dependResources: string[];
needGen: boolean;
key: string;
alias: string[];
config: PreparerConfig;
public createdObjectNames: string[];
public constructor(
name: string,
className: string,
dependParameters: string[],
dependResources: string[],
key: string,
alias: string[],
needGen = false,
config: PreparerConfig = undefined,
) {
this.name = name;
this.className = className;
this.dependParameters = dependParameters;
this.dependResources = dependResources;
this.createdObjectNames = [];
this.key = key;
this.alias = alias;
this.needGen = needGen;
this.config = config;
}
}
const preparerInfos = {
[RESOUREGROUP]: new PreparerInfo('ResourceGroupPreparer', RESOUREGROUP, [], []),
[VIRTUALNETWORK]: new PreparerInfo(
'VirtualNetworkPreparer',
VIRTUALNETWORK,
['resource_group_key'],
[RESOUREGROUP],
),
[SUBNET]: new PreparerInfo(
'VnetSubnetPreparer',
SUBNET,
['resource_group_key', 'vnet_key'],
[RESOUREGROUP, VIRTUALNETWORK],
),
export const preparerInfos: { [key: string]: PreparerInfo } = {
[RESOUREGROUP]: new PreparerInfo('ResourceGroupPreparer', RESOUREGROUP, [], [], 'rg', [
'resource-group',
'resourceGroupName',
'resourceGroups',
]),
[STORAGEACCOUNT]: new PreparerInfo(
'StorageAccountPreparer',
STORAGEACCOUNT,
['resource_group_parameter_name'],
[RESOUREGROUP],
),
[NETWORKINTERFACE]: new PreparerInfo(
'VnetNicPreparer',
NETWORKINTERFACE,
['resource_group_key', 'vnet_key'],
[RESOUREGROUP, VIRTUALNETWORK],
'sa',
['storage-account', 'storageAccountName', 'storageAccounts'],
),
};
export function GenPreparerName(className: string): string {
const eps = new EnglishPluralizationService();
return Capitalize(eps.singularize(ToCamelCase(ToSnakeCase(className)))) + 'Preparer';
}
export function GenPreparerDependParamName(className: string): string {
const eps = new EnglishPluralizationService();
return ToSnakeCase(eps.singularize(className)) + '_key';
}
export function LoadPreparesConfig(preparers: { [key: string]: PreparerConfig }) {
if (isNullOrUndefined(preparers)) return;
for (const resourceClass in preparers) {
// let resourceClass: string = config.resource;
const config = preparers[resourceClass];
let classKey = config.abbr;
if (isNullOrUndefined(classKey)) {
classKey = resourceClass;
}
// resourceClassKeys[resourceClass] = classKey;
// resourceLanguages[resourceClass] = [resourceClass];
const alias = [resourceClass];
if (config.alias) {
alias.push(...config.alias);
}
if (typeof config.create === 'string') {
config.create = [config.create];
}
if (typeof config.delete === 'string') {
config.delete = [config.delete];
}
if (isNullOrUndefined(config.inits)) {
config.inits = {};
}
if (Object.getOwnPropertyNames(config.inits).indexOf('name_prefix') < 0) {
config.inits['name_prefix'] = 'clitest.' + classKey;
}
if (Object.getOwnPropertyNames(config.inits).indexOf('random_name_length') < 0) {
config.inits['random_name_length'] = 24;
}
let depends: string[] = config.create
.concat(config.delete)
.join('\n')
.match(/\{.*?\}/g);
depends = depends.map((x: string) => {
return x.substr(1, x.length - 2);
});
depends = Array.from(new Set(depends));
const nameIndex = depends.indexOf('name');
if (nameIndex !== -1) {
depends.splice(nameIndex, 1);
}
// resourceClassDepends[resourceClass] = depends;
preparerInfos[resourceClass] = new PreparerInfo(
GenPreparerName(resourceClass),
resourceClass,
depends.map(GenPreparerDependParamName),
depends,
classKey,
alias,
true,
config,
);
}
}
export class PreparerEntity {
info: PreparerInfo;
objectName: string;
@ -481,11 +553,26 @@ function singlizeLast(word: string) {
return ws.join('-');
}
const keyCache = {}; // className+objectname->key
const keyCache = {}; //class_name+objectname->key
const formalCache = {};
const keySeq = {}; // className ->seq
const keySeq = {}; // class_name ->seq
const uniqueNames = {};
function addUniqueName(className: string, objectName: string): string {
let ret = objectName;
if (azOptions?.[CodeGenConstants.testUniqueResource]) {
if (Object.prototype.hasOwnProperty.call(uniqueNames, className)) {
ret = uniqueNames[className];
} else {
uniqueNames[className] = ret;
}
}
return ret;
}
export function getResourceKey(className: string, objectName: string, formalName = false): string {
const longKey = (resourceClassKeys[className] || className) + '_' + objectName;
const originObjectName = addUniqueName(className, objectName);
const longKey = (preparerInfos[className]?.key || className) + '_' + originObjectName;
if (formalName && longKey in formalCache) {
return formalCache[longKey];
}
@ -494,7 +581,7 @@ export function getResourceKey(className: string, objectName: string, formalName
}
if (Object.prototype.hasOwnProperty.call(keySeq, className)) {
const key = (resourceClassKeys[className] || className) + '_' + keySeq[className];
const key = (preparerInfos[className]?.key || className) + '_' + keySeq[className];
keySeq[className] += 1;
formalCache[longKey] = ToCamelCase(`my-${singlizeLast(className)}${keySeq[className] - 1}`);
if (preparerInfos[className]?.name) {
@ -510,11 +597,11 @@ export function getResourceKey(className: string, objectName: string, formalName
formalCache[longKey] = ToCamelCase(`my-${singlizeLast(className)}`);
if (preparerInfos[className]?.name) {
// is external resource
keyCache[longKey] = resourceClassKeys[className] || className;
keyCache[longKey] = preparerInfos[className]?.key || className;
} else {
// is internal resource
// generally, internal resource objectName is shorter than className
// keyCache[longKey] = objectName;
// generally, internal resource object_name is shorter than class_name
// keyCache[longKey] = object_name;
keyCache[longKey] = ToCamelCase(`my-${singlizeLast(className)}`);
}
}
@ -544,8 +631,6 @@ export class ResourcePool {
entitys: PreparerEntity[],
preparings: string[][],
) {
if (className === SUBNET) return; // use default subnet, no need to prepare it.
function inPreparings(): boolean {
for (const [pCName, pOName] of preparings) {
if (className === pCName && objectName === pOName) return true;
@ -660,6 +745,7 @@ export class ResourcePool {
objectName: string,
parentObject: ResourceObject,
): ResourceObject {
objectName = addUniqueName(className, objectName);
const resources: Map<string, ResourceClass> = parentObject
? parentObject.subResources
: this.root;
@ -806,6 +892,7 @@ export class ResourcePool {
}
public addMapResource(className: string, objectName: string): ResourceObject {
objectName = addUniqueName(className, objectName);
const resourceObject = this.findTreeResource(className, objectName, this.root);
if (resourceObject) {
return resourceObject;
@ -822,14 +909,53 @@ export class ResourcePool {
return this.map[className].objects[objectName];
}
public isResource(language: string): string | null {
public matchFullType(preparerConfig: PreparerConfig, instanceName: string, fullType: string[]) {
const configedFullType = preparerConfig?.fullType?.split('/');
if (isNullOrUndefined(configedFullType) || isNullOrUndefined(fullType)) return true;
if (configedFullType.length != fullType.length) return false;
for (let i = 0; i < configedFullType.length; i++) {
const resourceA = configedFullType[i];
const resourceB = fullType[i];
if (
resourceA.toLowerCase() != resourceB.toLowerCase() &&
this.isResource(resourceA, instanceName) != this.isResource(resourceB, instanceName)
)
return false;
}
return true;
}
public isResource(
language: string,
instanceName: string,
fullType: string[] = undefined,
): string | null {
if (language.startsWith('--')) language = language.substr(2);
for (const resource in resourceLanguages) {
for (const resourceLanguage of resourceLanguages[resource]) {
if (resourceLanguage.toLowerCase() === language.toLowerCase()) return resource;
let classResource = null;
let instanceResource = null;
for (const resource in preparerInfos) {
for (const resourceLanguage of preparerInfos[resource]?.alias || []) {
if (
resourceLanguage.toLowerCase() == language.toLowerCase() &&
this.matchFullType(preparerInfos[resource]?.config, instanceName, fullType)
) {
if (isNullOrUndefined(preparerInfos[resource]?.config?.forInstance)) {
classResource = resource;
} else if (
typeof instanceName === 'string' &&
preparerInfos[resource]?.config?.forInstance?.toLowerCase() ==
instanceName?.toLowerCase()
) {
instanceResource = resource;
}
}
}
}
return null;
if (isNullOrUndefined(instanceName)) {
return classResource;
}
return instanceResource || classResource;
}
private formatable(str: string, placeholders: string[]) {
@ -837,6 +963,17 @@ export class ResourcePool {
for (const placeholder of placeholders) {
str = str.split(`{${placeholder}}`).join(placeholder);
}
// apply replace in testResource scenario
let p = str.indexOf('$(');
let q = 0;
while (p >= 0 && q >= 0) {
q = str.indexOf(')', p);
if (q >= 0) {
str = str.slice(0, p) + '{' + str.slice(p + 2, q) + '}' + str.slice(q + 1);
p = str.indexOf('$(');
}
}
return str;
}
@ -1048,21 +1185,24 @@ export class ResourcePool {
this.useSubscription = true;
let i = 3;
let resourceObject: ResourceObject = null;
const fullType: string[] = [];
while (i < nodes.length - 1) {
const resource = this.isResource(nodes[i]);
if (nodes[i].toLowerCase() == 'providers') {
fullType.push(nodes[i + 1].toLowerCase());
} else {
if (fullType.length >= 1) {
fullType.push(nodes[i].toLowerCase());
}
}
const resource = this.isResource(nodes[i], nodes[i + 1], fullType);
if (resource) {
if (resource === SUBNET) {
// since the subnet can't be created with rand name, just use the dfault one.
nodes[i + 1] = 'default';
} else {
resourceObject = this.addTreeResource(resource, nodes[i + 1], resourceObject);
nodes[i + 1] = resourceObject.placeholder(isTest);
if (placeholders.indexOf(resourceObject.placeholder(isTest)) < 0) {
placeholders.push(resourceObject.placeholder(isTest));
}
if (resources.indexOf(resource) < 0) {
resources.push(resource);
}
resourceObject = this.addTreeResource(resource, nodes[i + 1], resourceObject);
nodes[i + 1] = resourceObject.placeholder(isTest);
if (placeholders.indexOf(resourceObject.placeholder(isTest)) < 0) {
placeholders.push(resourceObject.placeholder(isTest));
}
if (resources.indexOf(resource) < 0) {
resources.push(resource);
}
} else {
nodes[i + 1] = this.getPlaceholder(nodes[i + 1], isTest);
@ -1086,13 +1226,9 @@ export class ResourcePool {
if (paramName.startsWith('--')) {
paramName = paramName.substr(2);
}
const resource = this.isResource(paramName);
const resource = this.isResource(paramName, paramValue);
if (!resource) {
return this.getPlaceholder(paramValue, isTest);
}
if (resource === SUBNET) {
// since the subnet can't be created with rand name, just use the dfault one.
return 'default';
return this.getPlaceholder(paramValue, isTest, null, resource);
}
const resourceObject = this.addMapResource(resource, paramValue);
if (resourceObject) {
@ -1106,9 +1242,11 @@ export class ResourcePool {
objectName: string,
isTest: boolean,
placeholders: string[] = null,
targetClassName = undefined,
): string {
// find in MapResource
for (const className in this.map) {
if (!isNullOrUndefined(targetClassName) && className != targetClassName) continue;
if (
!isNullOrUndefined(this.map[className].objects) &&
Object.prototype.hasOwnProperty.call(this.map[className].objects, objectName)
@ -1124,7 +1262,7 @@ export class ResourcePool {
}
// find in TreeResource
const resourceObject = this.findTreeResource(null, objectName, this.root);
const resourceObject = this.findTreeResource(targetClassName, objectName, this.root);
if (resourceObject) {
const ret = resourceObject.placeholder(isTest);
if (!isNullOrUndefined(placeholders)) {
@ -1147,10 +1285,24 @@ export class ResourcePool {
return objectName;
}
public addResourcesInfo(resources: any) {
public addResourcesInfo(resources: Record<string, any>) {
for (const className in resources) {
resourceClassKeys[className] = className; // TODO: brief key for internal resources
resourceLanguages[className] = resources[className];
if (!(className in preparerInfos)) {
preparerInfos[className] = new PreparerInfo(
null,
className,
[],
[],
className,
resources[className],
);
} else {
preparerInfos[className].key = className; // TODO: brief key for internal resources
for (const a of resources[className]) {
if (preparerInfos[className].alias.indexOf(a) < 0)
preparerInfos[className].alias.push(a);
}
}
}
}
@ -1160,21 +1312,21 @@ export class ResourcePool {
dependParameters: string[],
createdObjectNames: string[],
) {
if (!(resourceClassName in resourceClassDepends)) {
resourceClassDepends[resourceClassName] = deepCopy(dependResources);
if (!(resourceClassName in preparerInfos)) {
preparerInfos[resourceClassName] = new PreparerInfo(
null,
resourceClassName,
dependParameters,
dependResources,
deepCopy(dependResources) as string[],
resourceClassName,
[resourceClassName],
);
} else {
for (let i = 0; i < dependResources.length; i++) {
const dependResource = dependResources[i];
if (resourceClassDepends[resourceClassName].indexOf(dependResource) < 0) {
resourceClassDepends[resourceClassName].push(dependResource);
if (preparerInfos[resourceClassName].dependResources.indexOf(dependResource) < 0) {
preparerInfos[resourceClassName].dependParameters.push(dependParameters[i]);
preparerInfos[resourceClassName].dependResources.push(dependResources[i]);
preparerInfos[resourceClassName].dependResources.push(dependResource);
}
}
}
@ -1187,7 +1339,7 @@ export class ResourcePool {
}
public isDependResource(child: string, parent: string) {
const depends = resourceClassDepends[child];
const depends = preparerInfos[child].dependResources;
return depends && depends.indexOf(parent) >= 0;
}
@ -1210,4 +1362,115 @@ export class ResourcePool {
resource.exampleParams = [];
}
}
public testDefs: TestDefinitionFile[] = [];
public async loadTestResources() {
function getSwaggerFolder() {
const parentsOptions = AzConfiguration.getValue(CodeGenConstants.parents);
for (const k in parentsOptions) {
const v: string = parentsOptions[k];
if (k.endsWith('.json') && typeof v === 'string' && v.startsWith('file:///')) {
if (process.platform.toLowerCase().startsWith('win')) {
return v.slice('file:///'.length);
}
return v.slice('file:///'.length - 1);
}
}
return undefined;
}
const loader = new TestResourceLoader({
useJsonParser: false,
checkUnderFileRoot: false,
fileRoot: getSwaggerFolder(),
swaggerFilePaths: AzConfiguration.getValue(CodeGenConstants.inputFile),
});
for (const testResource of AzConfiguration.getValue(CodeGenConstants.testResources) || []) {
const testDef = await loader.load(testResource[CodeGenConstants.test]);
this.testDefs.push(testDef);
}
}
public generateArmTemplate(files: Record<string, any>, templateFolder: string) {
for (const testDef of this.testDefs) {
for (let prepareStep of testDef.prepareSteps) {
if ((prepareStep as TestStepArmTemplateDeployment).armTemplateDeployment) {
prepareStep = prepareStep as TestStepArmTemplateDeployment;
files[
path.join(templateFolder, prepareStep.armTemplateDeployment)
] = JSON.stringify(prepareStep.armTemplatePayload, null, 4).split('\n');
}
}
}
}
public setupWithArmTemplate(): string[] {
const ret: string[] = [];
for (const testDef of this.testDefs) {
for (const prepareStep of testDef.prepareSteps) {
if ((prepareStep as TestStepArmTemplateDeployment).armTemplateDeployment) {
const templateFile = (prepareStep as TestStepArmTemplateDeployment)
.armTemplateDeployment;
ret.push(
` cmd = "az deployment group create --resource-group {{rg}} --template-file \\"{}\\"".format(os.path.join(TEST_DIR, '${templateFile}'))`,
);
ret.push(` o = test.cmd(cmd).get_output_in_json()`);
ret.push(
` kwargs = {k: v.get("value") for k, v in o.get('properties', {}).get('outputs', {}).items()}`,
);
ret.push(` test.kwargs.update(kwargs)`);
}
}
}
if (ret.length == 0) {
ret.push(' pass');
}
return ret;
}
public generateTestScenario() {
const cliScenario = {};
for (const testDef of this.testDefs) {
for (const testScenario of testDef.testScenarios) {
cliScenario[testScenario.description] = [];
for (let step of testScenario.steps) {
if ((step as TestStepExampleFileRestCall).exampleId) {
step = step as TestStepExampleFileRestCall;
this.applyTestResourceReplace(step);
cliScenario[testScenario.description].push({
name: step.exampleId,
step: step,
});
}
}
}
}
return cliScenario;
}
public get hasTestResourceScenario(): boolean {
return this.testDefs.length > 0;
}
public applyTestResourceReplace(step: TestStepExampleFileRestCall) {
for (const replace of step.replace) {
if (replace.pathInBody) {
for (const k in step.exampleTemplate.parameters) {
if (checkNested(step.exampleTemplate.parameters[k], replace.pathInBody)) {
setPathValue(
step.exampleTemplate.parameters[k],
replace.pathInBody,
replace.to,
);
}
}
}
if (replace.pathInExample) {
if (checkNested(step.exampleTemplate, replace.pathInBody)) {
setPathValue(step.exampleTemplate, replace.pathInBody, replace.to);
}
}
}
}
}

Просмотреть файл

@ -8,152 +8,37 @@
# regenerated.
# --------------------------------------------------------------------------
import os
from datetime import datetime
from azure_devtools.scenario_tests import SingleValueReplacer
from azure.cli.testsdk.preparers import NoTrafficRecordingPreparer
from azure.cli.testsdk.exceptions import CliTestError
from azure.cli.testsdk.reverse_dependency import get_dummy_cli
{% for preparerData in preparers %}
KEY_RESOURCE_GROUP = 'rg'
KEY_VIRTUAL_NETWORK = 'vnet'
KEY_VNET_SUBNET = 'subnet'
KEY_VNET_NIC = 'nic'
class VirtualNetworkPreparer(NoTrafficRecordingPreparer, SingleValueReplacer):
def __init__(self, name_prefix='clitest.vn',
parameter_name='virtual_network',
resource_group_name=None,
resource_group_key=KEY_RESOURCE_GROUP,
dev_setting_name='AZURE_CLI_TEST_DEV_VIRTUAL_NETWORK_NAME',
random_name_length=24, key=KEY_VIRTUAL_NETWORK):
if ' ' in name_prefix:
raise CliTestError(
'Error: Space character in name prefix \'%s\'' % name_prefix)
super(VirtualNetworkPreparer, self).__init__(
name_prefix, random_name_length)
class {{preparerData.className}}(NoTrafficRecordingPreparer, SingleValueReplacer):
def __init__(self,
{%- for paramPair in preparerData.initParamPairs %}
{{paramPair[0]}}={{paramPair[1]}},
{%- endfor %}
):
super({{preparerData.className}}, self).__init__(name_prefix, random_name_length)
self.cli_ctx = get_dummy_cli()
self.parameter_name = parameter_name
self.key = key
self.resource_group_name = resource_group_name
self.resource_group_key = resource_group_key
self.dev_setting_name = os.environ.get(dev_setting_name, None)
{%- for attribute in preparerData.attributes %}
self.{{attribute}} = {{attribute}}
{%- endfor %}
def create_resource(self, name, **_):
if self.dev_setting_name:
return {self.parameter_name: self.dev_setting_name, }
if not self.resource_group_name:
self.resource_group_name = self.test_class_instance.kwargs.get(
self.resource_group_key)
if not self.resource_group_name:
raise CliTestError("Error: No resource group configured!")
tags = {'product': 'azurecli', 'cause': 'automation',
'date': datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')}
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()])
template = 'az network vnet create --resource-group {} --name {} --subnet-name default --tag ' + tags
self.live_only_execute(self.cli_ctx, template.format(
self.resource_group_name, name))
cmd = '{{preparerData.createFunc.cmdTemplate}}'
{% if preparerData.createFunc.cmdFormats.length > 0 -%}
cmd = cmd.format({{preparerData.createFunc.cmdFormats|join(", ")}})
{% endif -%}
self.live_only_execute(self.cli_ctx, cmd)
self.test_class_instance.kwargs[self.key] = name
return {self.parameter_name: name}
return {self.key: name}
def remove_resource(self, name, **_):
# delete vnet if test is being recorded and if the vnet is not a dev rg
if not self.dev_setting_name:
self.live_only_execute(
self.cli_ctx,
'az network vnet delete --name {} --resource-group {}'.format(name, self.resource_group_name))
class VnetSubnetPreparer(NoTrafficRecordingPreparer, SingleValueReplacer):
def __init__(self, name_prefix='clitest.vn',
parameter_name='subnet',
resource_group_key=KEY_RESOURCE_GROUP,
vnet_key=KEY_VIRTUAL_NETWORK,
address_prefixes="11.0.0.0/24",
dev_setting_name='AZURE_CLI_TEST_DEV_VNET_SUBNET_NAME',
key=KEY_VNET_SUBNET):
if ' ' in name_prefix:
raise CliTestError(
'Error: Space character in name prefix \'%s\'' % name_prefix)
super(VnetSubnetPreparer, self).__init__(name_prefix, 15)
self.cli_ctx = get_dummy_cli()
self.parameter_name = parameter_name
self.key = key
self.resource_group = [resource_group_key, None]
self.vnet = [vnet_key, None]
self.address_prefixes = address_prefixes
self.dev_setting_name = os.environ.get(dev_setting_name, None)
def create_resource(self, name, **_):
if self.dev_setting_name:
return {self.parameter_name: self.dev_setting_name, }
if not self.resource_group[1]:
self.resource_group[1] = self.test_class_instance.kwargs.get(
self.resource_group[0])
if not self.resource_group[1]:
raise CliTestError("Error: No resource group configured!")
if not self.vnet[1]:
self.vnet[1] = self.test_class_instance.kwargs.get(self.vnet[0])
if not self.vnet[1]:
raise CliTestError("Error: No vnet configured!")
self.test_class_instance.kwargs[self.key] = 'default'
return {self.parameter_name: name}
def remove_resource(self, name, **_):
pass
class VnetNicPreparer(NoTrafficRecordingPreparer, SingleValueReplacer):
def __init__(self, name_prefix='clitest.nic',
parameter_name='subnet',
resource_group_key=KEY_RESOURCE_GROUP,
vnet_key=KEY_VIRTUAL_NETWORK,
dev_setting_name='AZURE_CLI_TEST_DEV_VNET_NIC_NAME',
key=KEY_VNET_NIC):
if ' ' in name_prefix:
raise CliTestError(
'Error: Space character in name prefix \'%s\'' % name_prefix)
super(VnetNicPreparer, self).__init__(name_prefix, 15)
self.cli_ctx = get_dummy_cli()
self.parameter_name = parameter_name
self.key = key
self.resource_group = [resource_group_key, None]
self.vnet = [vnet_key, None]
self.dev_setting_name = os.environ.get(dev_setting_name, None)
def create_resource(self, name, **_):
if self.dev_setting_name:
return {self.parameter_name: self.dev_setting_name, }
if not self.resource_group[1]:
self.resource_group[1] = self.test_class_instance.kwargs.get(
self.resource_group[0])
if not self.resource_group[1]:
raise CliTestError("Error: No resource group configured!")
if not self.vnet[1]:
self.vnet[1] = self.test_class_instance.kwargs.get(self.vnet[0])
if not self.vnet[1]:
raise CliTestError("Error: No vnet configured!")
template = 'az network nic create --resource-group {} --name {} --vnet-name {} --subnet default '
self.live_only_execute(self.cli_ctx, template.format(
self.resource_group[1], name, self.vnet[1]))
self.test_class_instance.kwargs[self.key] = name
return {self.parameter_name: name}
def remove_resource(self, name, **_):
if not self.dev_setting_name:
self.live_only_execute(
self.cli_ctx,
'az network nic delete --name {} --resource-group {}'.format(name, self.resource_group[1]))
cmd = '{{preparerData.removeFunc.cmdTemplate}}'
{% if preparerData.removeFunc.cmdFormats.length > 0 -%}
cmd = cmd.format({{preparerData.removeFunc.cmdFormats|join(", ")}})
{% endif -%}
self.live_only_execute(self.cli_ctx, cmd)
{% endfor -%}

Просмотреть файл

@ -726,3 +726,39 @@ export function getGitStatus(folder: string) {
export function isNullOrUndefined(obj: any) {
return obj === null || obj === undefined;
}
export function setPathValue(obj, path, value) {
if (Object(obj) !== obj) return obj; // When obj is not an object
// If not yet an array, get the keys from the string-path
if (!Array.isArray(path)) path = path.toString().match(/[^.[\]]+/g) || [];
path.slice(0, -1).reduce(
(
a,
c,
i, // Iterate all of them except the last one
) =>
Object(a[c]) === a[c] // Does the key exist and is its value an object?
? // Yes: then follow that path
a[c]
: // No: create the key. Is the next key a potential array-index?
(a[c] =
Math.abs(path[i + 1]) >> 0 === +path[i + 1]
? [] // Yes: assign a new array object
: {}), // No: assign a new plain object
obj,
)[path[path.length - 1]] = value; // Finally assign the value to the last key
return obj; // Return the top-level object to allow chaining
}
export function checkNested(obj, path: string) {
if (Object(obj) !== obj) return false; // When obj is not an object
const args = path.split('.');
for (let i = 0; i < args.length; i++) {
if (!obj || !(args[i] in obj)) {
return false;
}
obj = obj[args[i]];
}
return true;
}

Просмотреть файл

@ -107,7 +107,7 @@ export enum CodeGenConstants {
debug = 'debug',
use = 'use',
directive = 'directive',
parents = '_parents',
parents = '__parents',
azOutputFolder = 'az-output-folder',
generationMode = 'generation-mode',
clearOutputFolder = 'clear-output-folder',
@ -121,6 +121,9 @@ export enum CodeGenConstants {
azureCliExtFolder = 'azure-cli-extension-folder',
pythonSdkOutputFolder = 'python-sdk-output-folder',
cliCoreLib = 'cli-core-lib',
inputFile = 'input-file',
testResources = 'test-resources',
preparers = 'preparers',
// some configuration keys under az section
namespace = 'namespace',
@ -129,6 +132,7 @@ export enum CodeGenConstants {
clientBaseUrlBound = 'client-base-url-bound',
clientSubscriptionBound = 'client-subscription-bound',
clientAuthenticationPolicy = 'client-authentication-policy',
testUniqueResource = 'test-unique-resource',
// default constant values
minCliCoreVersion = '2.15.0',
@ -138,6 +142,9 @@ export enum CodeGenConstants {
AZ_ENTRY_CODE_MODEL_NAME = 'az-entry-code-model.yaml',
PYLINT_MAX_CODE_LENGTH = 119,
PYLINT_MAX_OPERATION_TEMPLATE_LENGTH = 92,
//configuration keys under test-resources section
test = 'test',
}
export interface AzextMetadata {

Просмотреть файл

@ -0,0 +1,9 @@
## Test-Resources
These settings is for the test prerequisites.
``` yaml
test-resources:
- test: ../input/test-scenarios/testDataExport.yaml
```

Просмотреть файл

@ -0,0 +1,29 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
},
"variables": {
"storageAccountName": "[uniqueString(resourceGroup().id)]"
},
"resources": [{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-06-01",
"name": "[variables('storageAccountName')]",
"kind": "StorageV2",
"location": "[resourceGroup().location]",
"sku": {
"name": "Standard_LRS"
}
}],
"outputs": {
"storageAccountId": {
"type": "string",
"value": "[resourceId('Microsoft.Storage/storageAccounts',variables('storageAccountName'))]"
},
"workspaceName": {
"type": "string",
"value": "[uniqueString(resourceGroup().id)]"
}
}
}

Просмотреть файл

@ -0,0 +1,15 @@
scope: ResourceGroup
prepareSteps:
- armTemplateDeployment: depSto.json
testScenarios:
- description: FakedTestScenario
steps:
- exampleFile: ../examples/Create_AttestationProvider.json
- exampleFile: ../examples/Update_AttestationProvider.json
replace:
- pathInBody: tags.Property1
to: $(storageAccountId)

Просмотреть файл

@ -0,0 +1,30 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {
"storageAccountName": "[uniqueString(resourceGroup().id)]"
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-06-01",
"name": "[variables('storageAccountName')]",
"kind": "StorageV2",
"location": "[resourceGroup().location]",
"sku": {
"name": "Standard_LRS"
}
}
],
"outputs": {
"storageAccountId": {
"type": "string",
"value": "[resourceId('Microsoft.Storage/storageAccounts',variables('storageAccountName'))]"
},
"workspaceName": {
"type": "string",
"value": "[uniqueString(resourceGroup().id)]"
}
}
}

Просмотреть файл

@ -12,76 +12,25 @@
from .. import try_manual
# EXAMPLE: /AttestationProviders/get/AttestationProviders_Get
@try_manual
def step_attestation_provider_show(test, rg, rg_2, rg_3, checks=None):
if checks is None:
checks = []
test.cmd('az attestation attestation-provider show '
'--provider-name "myattestationprovider" '
'--resource-group "{rg}"',
checks=checks)
# EXAMPLE: /AttestationProviders/get/AttestationProviders_List
@try_manual
def step_attestation_provider_provider_list(test, rg, rg_2, rg_3, checks=None):
if checks is None:
checks = []
test.cmd('az attestation attestation-provider provider list '
'-g ""',
checks=checks)
# EXAMPLE: /AttestationProviders/get/AttestationProviders_ListByResourceGroup
@try_manual
def step_attestation_provider_provider_list2(test, rg, rg_2, rg_3, checks=None):
if checks is None:
checks = []
test.cmd('az attestation attestation-provider provider list '
'--resource-group "{rg_2}"',
checks=checks)
# EXAMPLE: /AttestationProviders/patch/AttestationProviders_Update
@try_manual
def step_attestation_provider_update(test, rg, rg_2, rg_3, checks=None):
if checks is None:
checks = []
test.cmd('az attestation attestation-provider update '
'--provider-name "myattestationprovider" '
'--resource-group "{rg}" '
'--tags Property1="Value1" Property2="Value2" Property3="Value3"',
checks=checks)
# EXAMPLE: /AttestationProviders/delete/AttestationProviders_Delete
@try_manual
def step_attestation_provider_delete(test, rg, rg_2, rg_3, checks=None):
if checks is None:
checks = []
test.cmd('az attestation attestation-provider delete -y '
'--provider-name "myattestationprovider" '
'--resource-group "{rg_3}"',
checks=checks)
# EXAMPLE: /Operation/put/AttestationProviders_Create
# EXAMPLE: AttestationProviders_Create
@try_manual
def step_create_provider(test, rg, rg_2, rg_3, checks=None):
if checks is None:
checks = []
test.cmd('az attestation create-provider '
'--provider-name "myattestationprovider" '
'--resource-group "{rg}"',
'--resource-group "{rg_4}" '
'--provider-name "myattestationprovider"',
checks=checks)
# EXAMPLE: /Operation/get/Operations_List
# EXAMPLE: AttestationProviders_Update
@try_manual
def step_list_operation(test, rg, rg_2, rg_3, checks=None):
def step_attestation_provider_update(test, rg, rg_2, rg_3, checks=None):
if checks is None:
checks = []
test.cmd('az attestation list-operation',
test.cmd('az attestation attestation-provider update '
'--resource-group "{rg_4}" '
'--provider-name "myattestationprovider" '
'--tags Property1="{storageAccountId}" Property2="Value2" Property3="Value3"',
checks=checks)

Просмотреть файл

@ -7,16 +7,13 @@
# Changes may cause incorrect behavior and will be lost if the code is
# regenerated.
# --------------------------------------------------------------------------
# pylint: disable=line-too-long
import os
from azure.cli.testsdk import ScenarioTest
from azure.cli.testsdk import ResourceGroupPreparer
from .example_steps import step_list_operation
from .example_steps import step_create_provider
from .example_steps import step_attestation_provider_show
from .example_steps import step_attestation_provider_provider_list
from .example_steps import step_attestation_provider_provider_list2
from .example_steps import step_attestation_provider_delete
from .example_steps import step_attestation_provider_update
from .. import (
try_manual,
raise_if,
@ -29,50 +26,44 @@ TEST_DIR = os.path.abspath(os.path.join(os.path.abspath(__file__), '..'))
# Env setup_scenario
@try_manual
def setup_scenario(test, rg, rg_2, rg_3):
pass
# Env mytest
@try_manual
def mytest(test, rg, rg_2, rg_3):
pass
def setup_scenario(test, rg, rg_2, rg_3, rg_4):
cmd = "az deployment group create --resource-group {{rg}} --template-file \"{}\"".format(os.path.join(TEST_DIR, 'depSto.json'))
o = test.cmd(cmd).get_output_in_json()
kwargs = {k: v.get("value") for k, v in o.get('properties', {}).get('outputs', {}).items()}
test.kwargs.update(kwargs)
# Env cleanup_scenario
@try_manual
def cleanup_scenario(test, rg, rg_2, rg_3):
def cleanup_scenario(test, rg, rg_2, rg_3, rg_4):
pass
# Testcase: Scenario
@try_manual
def call_scenario(test, rg, rg_2, rg_3):
setup_scenario(test, rg, rg_2, rg_3)
step_list_operation(test, rg, rg_2, rg_3, checks=[])
step_create_provider(test, rg, rg_2, rg_3, checks=[])
step_attestation_provider_show(test, rg, rg_2, rg_3, checks=[])
mytest(test, rg, rg_2, rg_3)
step_attestation_provider_provider_list(test, rg, rg_2, rg_3, checks=[])
step_attestation_provider_provider_list2(test, rg, rg_2, rg_3, checks=[])
step_attestation_provider_delete(test, rg, rg_2, rg_3, checks=[])
cleanup_scenario(test, rg, rg_2, rg_3)
def call_scenario(test, rg, rg_2, rg_3, rg_4):
setup_scenario(test, rg, rg_2, rg_3, rg_4)
step_create_provider(test, rg, rg_2, rg_3, rg_4, checks=[])
step_attestation_provider_update(test, rg, rg_2, rg_3, rg_4, checks=[])
cleanup_scenario(test, rg, rg_2, rg_3, rg_4)
# Test class for Scenario
@try_manual
class AttestationScenarioTest(ScenarioTest):
class FakedTestScenarioScenarioTest(ScenarioTest):
def __init__(self, *args, **kwargs):
super(AttestationScenarioTest, self).__init__(*args, **kwargs)
super(FakedTestScenarioScenarioTest, self).__init__(*args, **kwargs)
@ResourceGroupPreparer(name_prefix='clitestattestation_MyResourceGroup'[:7], key='rg', parameter_name='rg')
@ResourceGroupPreparer(name_prefix='clitestattestation_testrg1'[:7], key='rg_2', parameter_name='rg_2')
@ResourceGroupPreparer(name_prefix='clitestattestation_sample-resource-group'[:7], key='rg_3',
parameter_name='rg_3')
def test_attestation_Scenario(self, rg, rg_2, rg_3):
call_scenario(self, rg, rg_2, rg_3)
@ResourceGroupPreparer(name_prefix='clitestattestation_$(resourceGroupName)'[:7], key='rg_4',
parameter_name='rg_4')
def test_FakedTestScenario_Scenario(self, rg, rg_2, rg_3, rg_4):
call_scenario(self, rg, rg_2, rg_3, rg_4)
calc_coverage(__file__)
raise_if()

Просмотреть файл

@ -12,7 +12,7 @@ az extension add --name managed-network
##### Create #####
```
az managed-network mn create \
--managed-network "{\\"location\\":\\"eastus\\",\\"tags\\":{},\\"managementGroups\\":[{\\"id\\":\\"/providers/Microsoft.Management/managementGroups/20000000-0001-0000-0000-000000000000\\"},{\\"id\\":\\"/providers/Microsoft.Management/managementGroups/20000000-0002-0000-0000-000000000000\\"}],\\"subscriptions\\":[{\\"id\\":\\"subscriptionA\\"},{\\"id\\":\\"subscriptionB\\"}],\\"virtualNetworks\\":[{\\"id\\":\\"/subscriptions/subscriptionC/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork\\"},{\\"id\\":\\"/subscriptions/subscriptionC/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork2\\"}],\\"subnets\\":[{\\"id\\":\\"/subscriptions/subscriptionC/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork3/subnets/default\\"},{\\"id\\":\\"/subscriptions/subscriptionC/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork3/subnets/default\\"}]}" \
--managed-network "{\\"location\\":\\"eastus\\",\\"tags\\":{},\\"managementGroups\\":[{\\"id\\":\\"/providers/Microsoft.Management/managementGroups/20000000-0001-0000-0000-000000000000\\"},{\\"id\\":\\"/providers/Microsoft.Management/managementGroups/20000000-0002-0000-0000-000000000000\\"}],\\"subscriptions\\":[{\\"id\\":\\"subscriptionA\\"},{\\"id\\":\\"subscriptionB\\"}],\\"virtualNetworks\\":[{\\"id\\":\\"/subscriptions/subscriptionC/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork\\"},{\\"id\\":\\"/subscriptions/subscriptionC/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork2\\"}],\\"subnets\\":[{\\"id\\":\\"/subscriptions/subscriptionC/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork3/subnets/mySubnet\\"},{\\"id\\":\\"/subscriptions/subscriptionC/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork3/subnets/mySubnet2\\"}]}" \
--name "myManagedNetwork" --resource-group "myResourceGroup"
```
##### List #####
@ -54,7 +54,7 @@ az managed-network mn scope-assignment delete --scope "subscriptions/subscriptio
##### Create #####
```
az managed-network mn group create --management-groups "[]" \
--subnets id="/subscriptions/subscriptionB/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork/subnets/default" id="/subscriptions/subscriptionB/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork2/subnets/default" \
--subnets id="/subscriptions/subscriptionB/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork/subnets/mySubnet" id="/subscriptions/subscriptionB/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork2/subnets/mySubnet2" \
--virtual-networks id="/subscriptionB/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/VnetA" \
--virtual-networks id="/subscriptionB/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/VnetB" \
--group-name "myManagedNetworkGroup" --managed-network-name "myManagedNetwork" --resource-group "myResourceGroup"

Просмотреть файл

@ -45,8 +45,8 @@ d\\":\\"/providers/Microsoft.Management/managementGroups/20000000-0002-0000-0000
criptionC/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork\\"},{\\"id\\":\\"\
/subscriptions/subscriptionC/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwor\
k2\\"}],\\"subnets\\":[{\\"id\\":\\"/subscriptions/subscriptionC/resourceGroups/myResourceGroup/providers/Microsoft.Net\
work/virtualNetworks/myVirtualNetwork3/subnets/default\\"},{\\"id\\":\\"/subscriptions/subscriptionC/resourceGroups/myR\
esourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork3/subnets/default\\"}]}" --name \
work/virtualNetworks/myVirtualNetwork3/subnets/mySubnet\\"},{\\"id\\":\\"/subscriptions/subscriptionC/resourceGroups/my\
ResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork3/subnets/mySubnet2\\"}]}" --name \
"myManagedNetwork" --resource-group "myResourceGroup"
"""
@ -188,11 +188,11 @@ helps['managed-network mn group create'] = """
- name: Create/Update Managed Network Group
text: |-
az managed-network mn group create --management-groups "[]" --subnets id="/subscriptions/subscriptionB/r\
esourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork/subnets/default" \
esourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork/subnets/mySubnet" \
id="/subscriptions/subscriptionB/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNe\
twork2/subnets/default" --virtual-networks id="/subscriptionB/resourceGroups/myResourceGroup/providers/Microsoft.Networ\
k/virtualNetworks/VnetA" --virtual-networks id="/subscriptionB/resourceGroups/myResourceGroup/providers/Microsoft.Netwo\
rk/virtualNetworks/VnetB" --group-name "myManagedNetworkGroup" --managed-network-name "myManagedNetwork" \
twork2/subnets/mySubnet2" --virtual-networks id="/subscriptionB/resourceGroups/myResourceGroup/providers/Microsoft.Netw\
ork/virtualNetworks/VnetA" --virtual-networks id="/subscriptionB/resourceGroups/myResourceGroup/providers/Microsoft.Net\
work/virtualNetworks/VnetB" --group-name "myManagedNetworkGroup" --managed-network-name "myManagedNetwork" \
--resource-group "myResourceGroup"
"""

Просмотреть файл

@ -25,9 +25,9 @@ def step_mn_create(test, rg, checks=None):
'":\\"/subscriptions/{subscription_id}/resourceGroups/{rg}/providers/Microsoft.Network/virtualNetworks/{vn'
'}\\"}},{{\\"id\\":\\"/subscriptions/{subscription_id}/resourceGroups/{rg}/providers/Microsoft.Network/vir'
'tualNetworks/{vn_2}\\"}}],\\"subnets\\":[{{\\"id\\":\\"/subscriptions/{subscription_id}/resourceGroups/{r'
'g}/providers/Microsoft.Network/virtualNetworks/{vn_3}/subnets/default\\"}},{{\\"id\\":\\"/subscriptions/{'
'subscription_id}/resourceGroups/{rg}/providers/Microsoft.Network/virtualNetworks/{vn_3}/subnets/default\\'
'"}}]}}" '
'g}/providers/Microsoft.Network/virtualNetworks/{vn_3}/subnets/{subnets}\\"}},{{\\"id\\":\\"/subscriptions'
'/{subscription_id}/resourceGroups/{rg}/providers/Microsoft.Network/virtualNetworks/{vn_3}/subnets/{subnet'
's_2}\\"}}]}}" '
'--name "{myManagedNetwork}" '
'--resource-group "{rg}"',
checks=checks)
@ -108,8 +108,8 @@ def step_mn_group_create(test, rg, checks=None):
test.cmd('az managed-network mn group create '
'--management-groups "[]" '
'--subnets id="/subscriptions/{subscription_id}/resourceGroups/{rg}/providers/Microsoft.Network/virtualNet'
'works/{vn}/subnets/default" id="/subscriptions/{subscription_id}/resourceGroups/{rg}/providers/Microsoft.'
'Network/virtualNetworks/{vn_2}/subnets/default" '
'works/{vn}/subnets/{subnets}" id="/subscriptions/{subscription_id}/resourceGroups/{rg}/providers/Microsof'
't.Network/virtualNetworks/{vn_2}/subnets/{subnets_2}" '
'--virtual-networks id="/subscriptionB/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualN'
'etworks/VnetA" '
'--virtual-networks id="/subscriptionB/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualN'

Просмотреть файл

@ -8,152 +8,72 @@
# regenerated.
# --------------------------------------------------------------------------
import os
from datetime import datetime
from azure_devtools.scenario_tests import SingleValueReplacer
from azure.cli.testsdk.preparers import NoTrafficRecordingPreparer
from azure.cli.testsdk.exceptions import CliTestError
from azure.cli.testsdk.reverse_dependency import get_dummy_cli
KEY_RESOURCE_GROUP = 'rg'
KEY_VIRTUAL_NETWORK = 'vnet'
KEY_VNET_SUBNET = 'subnet'
KEY_VNET_NIC = 'nic'
class VirtualNetworkPreparer(NoTrafficRecordingPreparer, SingleValueReplacer):
def __init__(self, name_prefix='clitest.vn',
parameter_name='virtual_network',
resource_group_name=None,
resource_group_key=KEY_RESOURCE_GROUP,
dev_setting_name='AZURE_CLI_TEST_DEV_VIRTUAL_NETWORK_NAME',
random_name_length=24, key=KEY_VIRTUAL_NETWORK):
if ' ' in name_prefix:
raise CliTestError(
'Error: Space character in name prefix \'%s\'' % name_prefix)
super(VirtualNetworkPreparer, self).__init__(
name_prefix, random_name_length)
def __init__(
self,
resource_group_key="rg",
key="vn",
name_prefix="clitest.vn",
random_name_length=24,
):
super(VirtualNetworkPreparer, self).__init__(name_prefix, random_name_length)
self.cli_ctx = get_dummy_cli()
self.parameter_name = parameter_name
self.key = key
self.resource_group_name = resource_group_name
self.resource_group_key = resource_group_key
self.dev_setting_name = os.environ.get(dev_setting_name, None)
self.name_prefix = name_prefix
self.random_name_length = random_name_length
def create_resource(self, name, **_):
if self.dev_setting_name:
return {self.parameter_name: self.dev_setting_name, }
if not self.resource_group_name:
self.resource_group_name = self.test_class_instance.kwargs.get(
self.resource_group_key)
if not self.resource_group_name:
raise CliTestError("Error: No resource group configured!")
tags = {'product': 'azurecli', 'cause': 'automation',
'date': datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')}
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()])
template = 'az network vnet create --resource-group {} --name {} --subnet-name default --tag ' + tags
self.live_only_execute(self.cli_ctx, template.format(
self.resource_group_name, name))
cmd = 'az network vnet create --resource-group {} --name {}'
cmd = cmd.format(self.test_class_instance.kwargs.get(self.resource_group_key), name)
self.live_only_execute(self.cli_ctx, cmd)
self.test_class_instance.kwargs[self.key] = name
return {self.parameter_name: name}
return {self.key: name}
def remove_resource(self, name, **_):
# delete vnet if test is being recorded and if the vnet is not a dev rg
if not self.dev_setting_name:
self.live_only_execute(
self.cli_ctx,
'az network vnet delete --name {} --resource-group {}'.format(name, self.resource_group_name))
cmd = 'az network vnet delete --resource-group {} --name {}'
cmd = cmd.format(self.test_class_instance.kwargs.get(self.resource_group_key), name)
self.live_only_execute(self.cli_ctx, cmd)
class VnetSubnetPreparer(NoTrafficRecordingPreparer, SingleValueReplacer):
def __init__(self, name_prefix='clitest.vn',
parameter_name='subnet',
resource_group_key=KEY_RESOURCE_GROUP,
vnet_key=KEY_VIRTUAL_NETWORK,
address_prefixes="11.0.0.0/24",
dev_setting_name='AZURE_CLI_TEST_DEV_VNET_SUBNET_NAME',
key=KEY_VNET_SUBNET):
if ' ' in name_prefix:
raise CliTestError(
'Error: Space character in name prefix \'%s\'' % name_prefix)
super(VnetSubnetPreparer, self).__init__(name_prefix, 15)
class SubnetPreparer(NoTrafficRecordingPreparer, SingleValueReplacer):
def __init__(
self,
virtual_network_key="vn",
resource_group_key="rg",
key="subnets",
name_prefix="clitest.subnets",
random_name_length=24,
):
super(SubnetPreparer, self).__init__(name_prefix, random_name_length)
self.cli_ctx = get_dummy_cli()
self.parameter_name = parameter_name
self.key = key
self.resource_group = [resource_group_key, None]
self.vnet = [vnet_key, None]
self.address_prefixes = address_prefixes
self.dev_setting_name = os.environ.get(dev_setting_name, None)
self.virtual_network_key = virtual_network_key
self.resource_group_key = resource_group_key
self.name_prefix = name_prefix
self.random_name_length = random_name_length
def create_resource(self, name, **_):
if self.dev_setting_name:
return {self.parameter_name: self.dev_setting_name, }
if not self.resource_group[1]:
self.resource_group[1] = self.test_class_instance.kwargs.get(
self.resource_group[0])
if not self.resource_group[1]:
raise CliTestError("Error: No resource group configured!")
if not self.vnet[1]:
self.vnet[1] = self.test_class_instance.kwargs.get(self.vnet[0])
if not self.vnet[1]:
raise CliTestError("Error: No vnet configured!")
self.test_class_instance.kwargs[self.key] = 'default'
return {self.parameter_name: name}
def remove_resource(self, name, **_):
pass
class VnetNicPreparer(NoTrafficRecordingPreparer, SingleValueReplacer):
def __init__(self, name_prefix='clitest.nic',
parameter_name='subnet',
resource_group_key=KEY_RESOURCE_GROUP,
vnet_key=KEY_VIRTUAL_NETWORK,
dev_setting_name='AZURE_CLI_TEST_DEV_VNET_NIC_NAME',
key=KEY_VNET_NIC):
if ' ' in name_prefix:
raise CliTestError(
'Error: Space character in name prefix \'%s\'' % name_prefix)
super(VnetNicPreparer, self).__init__(name_prefix, 15)
self.cli_ctx = get_dummy_cli()
self.parameter_name = parameter_name
self.key = key
self.resource_group = [resource_group_key, None]
self.vnet = [vnet_key, None]
self.dev_setting_name = os.environ.get(dev_setting_name, None)
def create_resource(self, name, **_):
if self.dev_setting_name:
return {self.parameter_name: self.dev_setting_name, }
if not self.resource_group[1]:
self.resource_group[1] = self.test_class_instance.kwargs.get(
self.resource_group[0])
if not self.resource_group[1]:
raise CliTestError("Error: No resource group configured!")
if not self.vnet[1]:
self.vnet[1] = self.test_class_instance.kwargs.get(self.vnet[0])
if not self.vnet[1]:
raise CliTestError("Error: No vnet configured!")
template = 'az network nic create --resource-group {} --name {} --vnet-name {} --subnet default '
self.live_only_execute(self.cli_ctx, template.format(
self.resource_group[1], name, self.vnet[1]))
cmd = 'az network vnet subnet create -n {} --vnet-name {} -g {} --address-prefixes "10.0.0.0/21"'
cmd = cmd.format(
name,
self.test_class_instance.kwargs.get(self.virtual_network_key),
self.test_class_instance.kwargs.get(self.resource_group_key),
)
self.live_only_execute(self.cli_ctx, cmd)
self.test_class_instance.kwargs[self.key] = name
return {self.parameter_name: name}
return {self.key: name}
def remove_resource(self, name, **_):
if not self.dev_setting_name:
self.live_only_execute(
self.cli_ctx,
'az network nic delete --name {} --resource-group {}'.format(name, self.resource_group[1]))
cmd = 'az network vnet subnet delete --name {} --resource-group {} --vnet-name {}'
cmd = cmd.format(
name,
self.test_class_instance.kwargs.get(self.resource_group_key),
self.test_class_instance.kwargs.get(self.virtual_network_key),
)
self.live_only_execute(self.cli_ctx, cmd)

Просмотреть файл

@ -12,6 +12,7 @@ import os
from azure.cli.testsdk import ScenarioTest
from azure.cli.testsdk import ResourceGroupPreparer
from .preparers import VirtualNetworkPreparer
from .preparers import SubnetPreparer
from .example_steps import step_mn_create
from .example_steps import step_mn_group_create
from .example_steps import step_managed_network_peering
@ -113,6 +114,10 @@ class ManagedNetworksscenario1Test(ScenarioTest):
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_VnetB'[:7], key='vn_2', resource_group_key='rg')
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_VnetC'[:7], key='vn_3', resource_group_key='rg')
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_myHubVnet'[:7], key='vn_4', resource_group_key='rg')
@SubnetPreparer(name_prefix='clitestmanaged_network_subnetA'[:7], key='subnets', virtual_network_key='vn',
resource_group_key='rg')
@SubnetPreparer(name_prefix='clitestmanaged_network_subnetB'[:7], key='subnets_2', virtual_network_key='vn_2',
resource_group_key='rg')
def test_ManagedNetworks_scenario1(self, rg):
call_scenario1(self, rg)
calc_coverage(__file__)
@ -124,6 +129,10 @@ class ManagedNetworksscenario1Test(ScenarioTest):
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_VnetB'[:7], key='vn_2', resource_group_key='rg')
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_VnetC'[:7], key='vn_3', resource_group_key='rg')
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_myHubVnet'[:7], key='vn_4', resource_group_key='rg')
@SubnetPreparer(name_prefix='clitestmanaged_network_subnetA'[:7], key='subnets', virtual_network_key='vn',
resource_group_key='rg')
@SubnetPreparer(name_prefix='clitestmanaged_network_subnetB'[:7], key='subnets_2', virtual_network_key='vn_2',
resource_group_key='rg')
def test_ManagedNetworks_scenario1_min(self, rg):
call_scenario1_min(self, rg)
calc_coverage(__file__)
@ -188,6 +197,10 @@ class ManagedNetworksscenario2Test(ScenarioTest):
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_VnetB'[:7], key='vn_2', resource_group_key='rg')
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_VnetC'[:7], key='vn_3', resource_group_key='rg')
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_myHubVnet'[:7], key='vn_4', resource_group_key='rg')
@SubnetPreparer(name_prefix='clitestmanaged_network_subnetA'[:7], key='subnets', virtual_network_key='vn',
resource_group_key='rg')
@SubnetPreparer(name_prefix='clitestmanaged_network_subnetB'[:7], key='subnets_2', virtual_network_key='vn_2',
resource_group_key='rg')
def test_ManagedNetworks_scenario2(self, rg):
call_scenario2(self, rg)
calc_coverage(__file__)
@ -199,6 +212,10 @@ class ManagedNetworksscenario2Test(ScenarioTest):
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_VnetB'[:7], key='vn_2', resource_group_key='rg')
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_VnetC'[:7], key='vn_3', resource_group_key='rg')
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_myHubVnet'[:7], key='vn_4', resource_group_key='rg')
@SubnetPreparer(name_prefix='clitestmanaged_network_subnetA'[:7], key='subnets', virtual_network_key='vn',
resource_group_key='rg')
@SubnetPreparer(name_prefix='clitestmanaged_network_subnetB'[:7], key='subnets_2', virtual_network_key='vn_2',
resource_group_key='rg')
def test_ManagedNetworks_scenario2_min(self, rg):
call_scenario2_min(self, rg)
calc_coverage(__file__)
@ -263,6 +280,10 @@ class ManagedNetworksscenario3Test(ScenarioTest):
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_VnetB'[:7], key='vn_2', resource_group_key='rg')
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_VnetC'[:7], key='vn_3', resource_group_key='rg')
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_myHubVnet'[:7], key='vn_4', resource_group_key='rg')
@SubnetPreparer(name_prefix='clitestmanaged_network_subnetA'[:7], key='subnets', virtual_network_key='vn',
resource_group_key='rg')
@SubnetPreparer(name_prefix='clitestmanaged_network_subnetB'[:7], key='subnets_2', virtual_network_key='vn_2',
resource_group_key='rg')
def test_ManagedNetworks_scenario3(self, rg):
call_scenario3(self, rg)
calc_coverage(__file__)
@ -274,6 +295,10 @@ class ManagedNetworksscenario3Test(ScenarioTest):
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_VnetB'[:7], key='vn_2', resource_group_key='rg')
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_VnetC'[:7], key='vn_3', resource_group_key='rg')
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_myHubVnet'[:7], key='vn_4', resource_group_key='rg')
@SubnetPreparer(name_prefix='clitestmanaged_network_subnetA'[:7], key='subnets', virtual_network_key='vn',
resource_group_key='rg')
@SubnetPreparer(name_prefix='clitestmanaged_network_subnetB'[:7], key='subnets_2', virtual_network_key='vn_2',
resource_group_key='rg')
def test_ManagedNetworks_scenario3_min(self, rg):
call_scenario3_min(self, rg)
calc_coverage(__file__)

Просмотреть файл

@ -12,6 +12,7 @@ import os
from azure.cli.testsdk import ScenarioTest
from azure.cli.testsdk import ResourceGroupPreparer
from .preparers import VirtualNetworkPreparer
from .preparers import SubnetPreparer
from .example_steps import step_mn_scope_assignment_create
from .example_steps import step_mn_scope_assignment_show
from .example_steps import step_mn_scope_assignment_list
@ -102,6 +103,10 @@ class ScopeAssignmentsScenarioTest(ScenarioTest):
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_VnetB'[:7], key='vn_2', resource_group_key='rg')
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_VnetC'[:7], key='vn_3', resource_group_key='rg')
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_myHubVnet'[:7], key='vn_4', resource_group_key='rg')
@SubnetPreparer(name_prefix='clitestmanaged_network_subnetA'[:7], key='subnets', virtual_network_key='vn',
resource_group_key='rg')
@SubnetPreparer(name_prefix='clitestmanaged_network_subnetB'[:7], key='subnets_2', virtual_network_key='vn_2',
resource_group_key='rg')
def test_ScopeAssignments_Scenario(self, rg):
call_scenario(self, rg)
calc_coverage(__file__)
@ -113,6 +118,10 @@ class ScopeAssignmentsScenarioTest(ScenarioTest):
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_VnetB'[:7], key='vn_2', resource_group_key='rg')
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_VnetC'[:7], key='vn_3', resource_group_key='rg')
@VirtualNetworkPreparer(name_prefix='clitestmanaged_network_myHubVnet'[:7], key='vn_4', resource_group_key='rg')
@SubnetPreparer(name_prefix='clitestmanaged_network_subnetA'[:7], key='subnets', virtual_network_key='vn',
resource_group_key='rg')
@SubnetPreparer(name_prefix='clitestmanaged_network_subnetB'[:7], key='subnets_2', virtual_network_key='vn_2',
resource_group_key='rg')
def test_ScopeAssignments_Scenario_min(self, rg):
call_scenario_min(self, rg)
calc_coverage(__file__)

Просмотреть файл

@ -207,8 +207,8 @@ ubscriptionA\\"},{\\"id\\":\\"subscriptionB\\"}],\\"virtualNetworks\\":[{\\"id\\
rceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork\\"},{\\"id\\":\\"/subscriptions/\
subscriptionC/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork2\\"}],\\"subn\
ets\\":[{\\"id\\":\\"/subscriptions/subscriptionC/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNet\
works/myVirtualNetwork3/subnets/default\\"},{\\"id\\":\\"/subscriptions/subscriptionC/resourceGroups/myResourceGroup/pr\
oviders/Microsoft.Network/virtualNetworks/myVirtualNetwork3/subnets/default\\"}]}" --name "myManagedNetwork" \
works/myVirtualNetwork3/subnets/mySubnet\\"},{\\"id\\":\\"/subscriptions/subscriptionC/resourceGroups/myResourceGroup/p\
roviders/Microsoft.Network/virtualNetworks/myVirtualNetwork3/subnets/mySubnet2\\"}]}" --name "myManagedNetwork" \
--resource-group "myResourceGroup"
```
##### <a name="ParametersManagedNetworksCreateOrUpdate#Create">Parameters</a>
@ -289,11 +289,11 @@ az managed-network mn group show --group-name "myManagedNetworkGroup" --managed-
##### <a name="ExamplesManagedNetworkGroupsCreateOrUpdate#Create">Example</a>
```
az managed-network mn group create --management-groups "[]" --subnets id="/subscriptions/subscriptionB/resourceGroups/m\
yResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork/subnets/default" \
yResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNetwork/subnets/mySubnet" \
id="/subscriptions/subscriptionB/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVirtualNe\
twork2/subnets/default" --virtual-networks id="/subscriptionB/resourceGroups/myResourceGroup/providers/Microsoft.Networ\
k/virtualNetworks/VnetA" --virtual-networks id="/subscriptionB/resourceGroups/myResourceGroup/providers/Microsoft.Netwo\
rk/virtualNetworks/VnetB" --group-name "myManagedNetworkGroup" --managed-network-name "myManagedNetwork" \
twork2/subnets/mySubnet2" --virtual-networks id="/subscriptionB/resourceGroups/myResourceGroup/providers/Microsoft.Netw\
ork/virtualNetworks/VnetA" --virtual-networks id="/subscriptionB/resourceGroups/myResourceGroup/providers/Microsoft.Net\
work/virtualNetworks/VnetB" --group-name "myManagedNetworkGroup" --managed-network-name "myManagedNetwork" \
--resource-group "myResourceGroup"
```
##### <a name="ParametersManagedNetworkGroupsCreateOrUpdate#Create">Parameters</a>

Просмотреть файл

@ -34,6 +34,7 @@ export class RenderDataBase {
await entry.init();
const model = new CodeModelCliImpl(session);
model.GenerateTestInit();
this.model = model;
}