Skip to content

Commit fd319d4

Browse files
authored
Merge pull request #1582 from Azure/sdkauto
Sdkauto
2 parents d3acf8b + c716195 commit fd319d4

File tree

12 files changed

+409
-53
lines changed

12 files changed

+409
-53
lines changed

.sdkauto/initScript.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
set -e
44

5+
npm install -g npm
6+
57
pushd generator
68

79
npm install

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"cwd": "${workspaceFolder}/generator",
4747
"args": [
4848
"${workspaceFolder}/generator/cmd/generateall.ts",
49-
"{\"localPath\":\"/home/me/workspace/azure-rest-api-specs\",\"readmeFiles\":[\"specification/signalr/resource-manager/readme.md\",\"specification/appplatform/resource-manager/readme.md\"],\"outputPath\":\"../generateOutput.json\"}"
49+
"{\"localPath\":\"../azure-rest-api-specs\",\"readmeFiles\":[\"specification/signalr/resource-manager/readme.md\",\"specification/appplatform/resource-manager/readme.md\"],\"outputPath\":\"../generateOutput.json\"}"
5050
]
5151
}
5252
],

generator/autogenlist.ts

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ScopeType, AutogenlistConfig } from './models';
1+
import { ScopeType, AutoGenConfig } from './models';
22
import { postProcessor as insightsApplicationPostProcessor } from './processors/Microsoft.Insights.Application';
33
import { postProcessor as resourcesPostProcessor } from './processors/Microsoft.Resources';
44
import { postProcessor as machineLearningPostProcessor } from './processors/Microsoft.MachineLearning';
@@ -7,7 +7,7 @@ import { postProcessor as storageProcessor } from './processors/Microsoft.Storag
77
import { lowerCaseEquals } from './utils';
88

99
// Run "npm run list-basepaths" to discover all the valid readme files to add to this list
10-
const autogenlist: AutogenlistConfig[] = [
10+
const autoGenList: AutoGenConfig[] = [
1111
{
1212
basePath: 'addons/resource-manager',
1313
namespace: 'Microsoft.Addons',
@@ -674,6 +674,23 @@ const autogenlist: AutogenlistConfig[] = [
674674
{
675675
basePath: 'keyvault/resource-manager',
676676
namespace: 'Microsoft.KeyVault',
677+
readmeTag: {
678+
'2016-10-01': [
679+
'Microsoft.KeyVault/stable/2016-10-01/keyvault.json',
680+
'Microsoft.KeyVault/stable/2016-10-01/providers.json',
681+
'Microsoft.KeyVault/stable/2016-10-01/secrets.json',
682+
],
683+
'2018-02-14': [
684+
'Microsoft.KeyVault/stable/2018-02-14/keyvault.json',
685+
'Microsoft.KeyVault/stable/2018-02-14/providers.json',
686+
'Microsoft.KeyVault/stable/2018-02-14/secrets.json',
687+
],
688+
'2018-02-14-preview': [
689+
'Microsoft.KeyVault/stable/2018-02-14-preview/keyvault.json',
690+
'Microsoft.KeyVault/stable/2018-02-14-preview/providers.json',
691+
'Microsoft.KeyVault/stable/2018-02-14-preview/secrets.json',
692+
],
693+
}
677694
},
678695
{
679696
basePath: 'hybridkubernetes/resource-manager',
@@ -727,10 +744,10 @@ const autogenlist: AutogenlistConfig[] = [
727744
}
728745
];
729746

730-
export function getAutogenlist(): AutogenlistConfig[] {
731-
return autogenlist;
747+
export function getAutoGenList(): AutoGenConfig[] {
748+
return autoGenList;
732749
}
733750

734-
export function findAutogenEntries(basePath: string): AutogenlistConfig[] {
735-
return autogenlist.filter(w => lowerCaseEquals(w.basePath, basePath));
751+
export function findAutogenEntries(basePath: string): AutoGenConfig[] {
752+
return autoGenList.filter(w => lowerCaseEquals(w.basePath, basePath));
736753
}

generator/cmd/findbasepath.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ executeSynchronous(async () => {
1515
// format basePath.
1616
basePath = `${basePath}/resource-manager`;
1717

18-
const autogenEntries = findAutogenEntries(basePath);
18+
const autoGenEntries = findAutogenEntries(basePath);
1919

20-
if (autogenEntries.length === 0) {
20+
if (autoGenEntries.length === 0) {
2121
// not onboarded in autogeneration
2222
console.log("false");
2323
return;

generator/cmd/generateall.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as constants from '../constants';
22
import { cloneAndGenerateBasePaths, getPackageString, resolveAbsolutePath, validateAndReturnReadmePath } from '../specs';
3-
import { SchemaConfiguration, generateSchemas, clearAutogeneratedSchemaRefs, saveAutogeneratedSchemaRefs } from '../generate';
4-
import { getAutogenlist } from '../autogenlist';
3+
import { SchemaConfiguration, generateSchemas, clearAutoGeneratedSchemaRefs, saveAutoGeneratedSchemaRefs } from '../generate';
4+
import { getAutoGenList } from '../autogenlist';
55
import chalk from 'chalk';
66
import { flatten } from 'lodash';
77
import { executeSynchronous, chunker, writeJsonFile } from '../utils';
@@ -26,9 +26,9 @@ function parseParams(): GenerateAllParams {
2626
executeSynchronous(async () => {
2727
const params = parseParams();
2828

29-
let filteredAutogenlist = getAutogenlist();
29+
let filteredAutoGenList = getAutoGenList();
3030
if (params.batchCount !== undefined && params.batchIndex !== undefined) {
31-
filteredAutogenlist = chunker(filteredAutogenlist, params.batchCount)[params.batchIndex];
31+
filteredAutoGenList = chunker(filteredAutoGenList, params.batchCount)[params.batchIndex];
3232
}
3333

3434
let localPath = params.localPath;
@@ -40,7 +40,7 @@ executeSynchronous(async () => {
4040
}
4141

4242
if (!!params.readmeFiles) {
43-
filteredAutogenlist = filteredAutogenlist.filter(c => {
43+
filteredAutoGenList = filteredAutoGenList.filter(c => {
4444
let r = params.readmeFiles?.find(f => f.startsWith('specification/' + c.basePath));
4545
if (!!r) {
4646
c.readmeFile = r;
@@ -51,34 +51,34 @@ executeSynchronous(async () => {
5151
);
5252
}
5353

54-
await clearAutogeneratedSchemaRefs(filteredAutogenlist);
54+
await clearAutoGeneratedSchemaRefs(filteredAutoGenList);
5555

5656
const schemaConfigs: SchemaConfiguration[] = [];
5757
const errors = [];
5858
const packages: Package[] = [];
59-
for (const autogenlistConfig of filteredAutogenlist) {
59+
for (const autoGenConfig of filteredAutoGenList) {
6060
let pkg = {
6161
path: ['schemas']
6262
} as Package;
6363
try {
64-
const readme = await validateAndReturnReadmePath(localPath, autogenlistConfig.readmeFile || autogenlistConfig.basePath);
64+
const readme = await validateAndReturnReadmePath(localPath, autoGenConfig.readmeFile || autoGenConfig.basePath);
6565
pkg.packageName = getPackageString(readme);
6666

67-
const newConfigs = await generateSchemas(readme, autogenlistConfig);
67+
const newConfigs = await generateSchemas(readme, autoGenConfig);
6868
schemaConfigs.push(...newConfigs);
6969
pkg.result = 'succeeded';
7070
} catch(error) {
71-
pkg.packageName = autogenlistConfig.basePath;
71+
pkg.packageName = autoGenConfig.basePath;
7272
pkg.result = 'failed';
73-
console.log(chalk.red(`Caught exception processing autogenlist entry ${autogenlistConfig.basePath}.`));
73+
console.log(chalk.red(`Caught exception processing autogenlist entry ${autoGenConfig.basePath}.`));
7474
console.log(chalk.red(error));
7575

7676
errors.push(error);
7777
}
7878
packages.push(pkg);
7979
}
8080

81-
await saveAutogeneratedSchemaRefs(flatten(schemaConfigs));
81+
await saveAutoGeneratedSchemaRefs(flatten(schemaConfigs));
8282

8383
if (!!params.outputPath) {
8484
const outputPath = await resolveAbsolutePath(params.outputPath);

generator/cmd/generatesingle.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as constants from '../constants';
22
import { cloneAndGenerateBasePaths, resolveAbsolutePath, validateAndReturnReadmePath, getPackageString } from '../specs';
3-
import { generateSchemas, saveAutogeneratedSchemaRefs } from '../generate';
3+
import { generateSchemas, saveAutoGeneratedSchemaRefs } from '../generate';
44
import process from 'process';
55
import { findAutogenEntries } from '../autogenlist';
66
import chalk from 'chalk';
@@ -24,20 +24,20 @@ executeSynchronous(async () => {
2424
}
2525

2626
const schemaConfigs = [];
27-
const autogenEntries = findAutogenEntries(basePath);
27+
const autoGenEntries = findAutogenEntries(basePath);
2828

29-
if (autogenEntries.length === 0) {
29+
if (autoGenEntries.length === 0) {
3030
const localSchemaConfigs = await generateSchemas(readme);
3131
schemaConfigs.push(...localSchemaConfigs);
3232
} else {
33-
for (const autogenlistConfig of autogenEntries) {
33+
for (const autoGenConfig of autoGenEntries) {
3434
console.log(`Using autogenlist config:`)
35-
console.log(chalk.green(JSON.stringify(autogenlistConfig, null, 2)));
35+
console.log(chalk.green(JSON.stringify(autoGenConfig, null, 2)));
3636

37-
const localSchemaConfigs = await generateSchemas(readme, autogenlistConfig);
37+
const localSchemaConfigs = await generateSchemas(readme, autoGenConfig);
3838
schemaConfigs.push(...localSchemaConfigs);
3939
}
4040
}
4141

42-
await saveAutogeneratedSchemaRefs(schemaConfigs);
42+
await saveAutoGeneratedSchemaRefs(schemaConfigs);
4343
});

generator/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const generatorRoot = path.resolve(__dirname, '../');
66
export const specsRepoPath = path.join(os.tmpdir(), 'schm_azspc');
77
export const specsRepoUri = 'https://github.com/azure/azure-rest-api-specs';
88
export const specsRepoCommitHash = 'origin/master';
9+
export const pathRegex = /(microsoft\.\w+)[\\\/]\S*[\\\/](\d{4}-\d{2}-\d{2}(|-preview))[\\\/]/i;
910

1011
export const autoRestVerboseOutput = false;
1112

generator/generate.ts

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import path from 'path';
22
import os from 'os';
33
import { findRecursive, findDirRecursive, executeCmd, rmdirRecursive, lowerCaseCompare, lowerCaseCompareLists, lowerCaseStartsWith, readJsonFile, writeJsonFile, safeMkdir, safeUnlink, fileExists, lowerCaseEquals, lowerCaseContains } from './utils';
44
import * as constants from './constants';
5+
import { prepareReadme } from './specs';
56
import chalk from 'chalk';
6-
import { ScopeType, AutogenlistConfig } from './models';
7+
import { ScopeType, AutoGenConfig } from './models';
78
import { get, set, flatten, uniq, concat, Dictionary, groupBy, keys, difference, pickBy } from 'lodash';
89

910
const autorestBinary = os.platform() === 'win32' ? 'autorest.cmd' : 'autorest';
@@ -44,10 +45,12 @@ export async function getApiVersionsByNamespace(readme: string): Promise<Diction
4445
return output;
4546
}
4647

47-
export async function generateSchemas(readme: string, autogenlistConfig?: AutogenlistConfig): Promise<SchemaConfiguration[]> {
48+
export async function generateSchemas(readme: string, autoGenConfig?: AutoGenConfig): Promise<SchemaConfiguration[]> {
49+
await prepareReadme(readme, autoGenConfig);
50+
4851
const apiVersionsByNamespace = pickBy(
4952
await getApiVersionsByNamespace(readme),
50-
(_, key) => !autogenlistConfig || lowerCaseEquals(key, autogenlistConfig.namespace));
53+
(_, key) => !autoGenConfig || lowerCaseEquals(key, autoGenConfig.namespace));
5154

5255
const namespaces = keys(apiVersionsByNamespace);
5356

@@ -63,7 +66,7 @@ export async function generateSchemas(readme: string, autogenlistConfig?: Autoge
6366
continue;
6467
}
6568

66-
const generatedSchemaConfig = await handleGeneratedSchema(readme, schemaPath, autogenlistConfig);
69+
const generatedSchemaConfig = await handleGeneratedSchema(readme, schemaPath, autoGenConfig);
6770

6871
schemaConfigs.push(generatedSchemaConfig);
6972
}
@@ -75,19 +78,19 @@ export async function generateSchemas(readme: string, autogenlistConfig?: Autoge
7578
return schemaConfigs;
7679
}
7780

78-
async function handleGeneratedSchema(readme: string, schemaPath: string, autogenlistConfig?: AutogenlistConfig) {
81+
async function handleGeneratedSchema(readme: string, schemaPath: string, autoGenConfig?: AutoGenConfig) {
7982
const namespace = path.basename(schemaPath.substring(0, schemaPath.lastIndexOf(path.extname(schemaPath))));
8083

81-
if (autogenlistConfig && autogenlistConfig.namespace.toLowerCase() !== namespace.toLowerCase()) {
84+
if (autoGenConfig && autoGenConfig.namespace.toLowerCase() !== namespace.toLowerCase()) {
8285
throw new Error(`Encountered unexpected namespace ${namespace} in readme ${readme}`);
8386
}
8487

8588
const apiVersion = path.basename(path.resolve(`${schemaPath}/..`));
8689

87-
const schemaConfig = await generateSchemaConfig(schemaPath, namespace, apiVersion, autogenlistConfig);
90+
const schemaConfig = await generateSchemaConfig(schemaPath, namespace, apiVersion, autoGenConfig);
8891

8992
const unknownScopeResources = schemaConfig.references.filter(x => x.scope & ScopeType.Unknown);
90-
if (autogenlistConfig && unknownScopeResources.length > 0) {
93+
if (autoGenConfig && unknownScopeResources.length > 0) {
9194
throw new Error(`Unable to determine scope for resource types ${unknownScopeResources.map(x => x.type).join(', ')} in readme ${readme}`);
9295
}
9396

@@ -111,8 +114,7 @@ async function generateSchema(readme: string, tmpFolder: string) {
111114
`--use=@autorest/azureresourceschema@${constants.azureresourceschemaVersion}`,
112115
'--azureresourceschema',
113116
`--output-folder=${tmpFolder}`,
114-
`--multiapi`,
115-
'--title=none',
117+
'--multiapi',
116118
'--pass-thru:subset-reducer',
117119
readme,
118120
];
@@ -144,8 +146,8 @@ function getFilePathFromRef(schemaRef: string) {
144146
return path.resolve(path.join(constants.schemasBasePath, schemaUri.substring(constants.schemasBaseUri.length + 1)));
145147
}
146148

147-
function assignScopesToUnknownReferences(knownReferences: SchemaReference[], unknownReferences: SchemaReference[], autogenlistConfig?: AutogenlistConfig) {
148-
const resourceConfig = (autogenlistConfig || {}).resourceConfig || [];
149+
function assignScopesToUnknownReferences(knownReferences: SchemaReference[], unknownReferences: SchemaReference[], autoGenConfig?: AutoGenConfig) {
150+
const resourceConfig = (autoGenConfig || {}).resourceConfig || [];
149151

150152
for (const schemaRef of unknownReferences) {
151153
const config = resourceConfig.find(c => lowerCaseCompare(c.type, schemaRef.type) === 0);
@@ -169,14 +171,14 @@ function getSchemaFileName(namespace: string, suffix: string | undefined) {
169171
return `${namespace}.${suffix}.json`;
170172
}
171173

172-
async function generateSchemaConfig(outputFile: string, namespace: string, apiVersion: string, autogenlistConfig?: AutogenlistConfig): Promise<SchemaConfiguration> {
173-
namespace = autogenlistConfig?.namespace ?? namespace;
174-
const suffix = autogenlistConfig?.suffix;
174+
async function generateSchemaConfig(outputFile: string, namespace: string, apiVersion: string, autoGenConfig?: AutoGenConfig): Promise<SchemaConfiguration> {
175+
namespace = autoGenConfig?.namespace ?? namespace;
176+
const suffix = autoGenConfig?.suffix;
175177
const relativePath = `${apiVersion}/${getSchemaFileName(namespace, suffix)}`;
176178

177179
let output = await readJsonFile(outputFile);
178-
if (autogenlistConfig?.postProcessor) {
179-
autogenlistConfig?.postProcessor(namespace, apiVersion, output);
180+
if (autoGenConfig?.postProcessor) {
181+
autoGenConfig?.postProcessor(namespace, apiVersion, output);
180182

181183
await writeJsonFile(outputFile, output);
182184
}
@@ -190,7 +192,7 @@ async function generateSchemaConfig(outputFile: string, namespace: string, apiVe
190192
];
191193

192194
const unknownReferences = getSchemaRefs(output, ScopeType.Unknown, 'unknown_resourceDefinitions');
193-
assignScopesToUnknownReferences(knownReferences, unknownReferences, autogenlistConfig);
195+
assignScopesToUnknownReferences(knownReferences, unknownReferences, autoGenConfig);
194196

195197
const references = [
196198
...knownReferences,
@@ -290,10 +292,10 @@ async function getCurrentTemplateRefs(scopeType: ScopeType, rootSchemaConfig: Ro
290292
return currentRefsOneOf.map(v => v['$ref']);
291293
}
292294

293-
export async function clearAutogeneratedSchemaRefs(autogenlist: AutogenlistConfig[]) {
295+
export async function clearAutoGeneratedSchemaRefs(autoGenList: AutoGenConfig[]) {
294296
RootSchemaConfigs.forEach(async (rootSchemaConfig, scopeType) => {
295297
const currentRefs = await getCurrentTemplateRefs(scopeType, rootSchemaConfig);
296-
const autogenlistedFiles = new Set(autogenlist.map(x => getSchemaFileName(x.namespace, x.suffix).toLowerCase()));
298+
const autogenlistedFiles = new Set(autoGenList.map(x => getSchemaFileName(x.namespace, x.suffix).toLowerCase()));
297299
const schemasToRemove = [];
298300
const schemasByFilePath = groupBy(currentRefs, getFilePathFromRef);
299301
// clean up existing schemas to detect deletions
@@ -311,7 +313,7 @@ export async function clearAutogeneratedSchemaRefs(autogenlist: AutogenlistConfi
311313
});
312314
}
313315

314-
export async function saveAutogeneratedSchemaRefs(schemaConfigs: SchemaConfiguration[]) {
316+
export async function saveAutoGeneratedSchemaRefs(schemaConfigs: SchemaConfiguration[]) {
315317
RootSchemaConfigs.forEach(async (rootSchemaConfig, scopeType) => {
316318
const refs = flatten(schemaConfigs
317319
.map(c => c.references

generator/models.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,25 @@ export enum ScopeType {
88
Extension = 1 << 5,
99
}
1010

11-
export interface AutogenlistConfig {
11+
export interface AutoGenConfig {
1212
basePath: string,
1313
namespace: string,
1414
readmeFile?: string,
15+
readmeTag?: ReadmeTag,
1516
suffix?: string,
16-
resourceConfig?: AutogenlistResourceConfig[],
17+
resourceConfig?: AutoGenResourceConfig[],
1718
postProcessor?: SchemaPostProcessor,
1819
}
1920

20-
export interface AutogenlistResourceConfig {
21+
export interface ReadmeTag {
22+
[apiVersion: string]: string[]
23+
}
24+
25+
export interface CodeBlock {
26+
readonly "input-file"?: ReadonlyArray<string>|string
27+
}
28+
29+
export interface AutoGenResourceConfig {
2130
type: string,
2231
scopes?: ScopeType,
2332
}

0 commit comments

Comments
 (0)