Skip to content

Commit c234fb1

Browse files
Merge pull request #3064 from Azure/ant/restore_resource
Bring back resources.json
2 parents c9d954d + eed27cd commit c234fb1

File tree

7 files changed

+19810
-3
lines changed

7 files changed

+19810
-3
lines changed

.github/workflows/generate-schemas.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ jobs:
114114
--batch-count ${{ env.BATCH_COUNT }}
115115
working-directory: generator
116116

117+
- name: Update resources.json
118+
run: |
119+
npm run list-resources
120+
working-directory: generator
121+
117122
- name: Push to autogenerate-batch branch
118123
uses: stefanzweifel/git-auto-commit-action@v5
119124
with:

.github/workflows/generate-single.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ jobs:
5959
--base-path '${{ github.event.inputs.single_path }}'
6060
working-directory: generator
6161

62+
- name: Update resources.json
63+
run: |
64+
npm run list-resources
65+
working-directory: generator
66+
6267
- name: Push to git branch
6368
uses: stefanzweifel/git-auto-commit-action@v5
6469
with:

generator/cmd/listresources.ts

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
import path from 'path';
4+
import { writeFile } from 'fs/promises';
5+
import { resourcesJsonPath, schemasBasePath, schemasBaseUri, } from '../constants';
6+
import { lowerCaseCompare, executeSynchronous, readJsonFile, lowerCaseStartsWith } from '../utils';
7+
8+
const rootSchemaPaths = [
9+
'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json',
10+
'https://schema.management.azure.com/schemas/common/definitions.json',
11+
'https://schema.management.azure.com/schemas/common/autogeneratedResources.json',
12+
'https://schema.management.azure.com/schemas/common/manuallyAddedResources.json',
13+
'https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json',
14+
'https://schema.management.azure.com/schemas/2019-08-01/tenantDeploymentTemplate.json',
15+
'https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json',
16+
];
17+
18+
async function readSchema(schemaUri: string) {
19+
if (!lowerCaseStartsWith(schemaUri, `${schemasBaseUri}/`)) {
20+
throw new Error(`Invalid schema Uri ${schemaUri}`);
21+
}
22+
23+
const filePath = path.join(schemasBasePath, schemaUri.substring(schemasBaseUri.length + 1));
24+
return await readJsonFile(filePath);
25+
}
26+
27+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
28+
function findAllReferences(input: any) {
29+
let refs: string[] = [];
30+
31+
for (const key of Object.keys(input)) {
32+
if (Array.isArray(input[key])) {
33+
for (const value of input[key]) {
34+
const foundRefs = findAllReferences(value);
35+
refs = refs.concat(foundRefs);
36+
}
37+
} else if (typeof input[key] === 'object') {
38+
const foundRefs = findAllReferences(input[key]);
39+
refs = refs.concat(foundRefs);
40+
} else if (key === '$ref' && typeof input[key] === 'string') {
41+
refs.push(input[key]);
42+
}
43+
}
44+
45+
return refs;
46+
}
47+
48+
async function getResourceInfo(schemaRef: string) {
49+
const schemaUri = schemaRef.split('#')[0];
50+
const relativeRef = schemaRef.split('#')[1].substring(1);
51+
52+
let schema = await readSchema(schemaUri);
53+
54+
for (const pathElement of relativeRef.split('/')) {
55+
schema = schema[pathElement];
56+
}
57+
58+
if (!schema?.properties?.type?.enum || !schema?.properties?.apiVersion?.enum) {
59+
throw new Error(`Unable to find expected properties for ${schemaRef}`)
60+
}
61+
62+
const resourceTypes: string[] = schema['properties']['type']['enum'];
63+
const apiVersions: string[] = schema['properties']['apiVersion']['enum'];
64+
65+
return resourceTypes.map(type => apiVersions.map(apiVersion => ({
66+
apiVersion,
67+
type,
68+
}))).reduce((a, b) => a.concat(b), []);
69+
}
70+
71+
async function findAllResourceReferences() {
72+
let allRefs: string[] = [];
73+
for (const rootSchemaPath of rootSchemaPaths) {
74+
const rootSchema = await readSchema(rootSchemaPath);
75+
const schemaRefs = findAllReferences(rootSchema)
76+
.filter(schema => schema.toLowerCase().startsWith(schemasBaseUri.toLowerCase() + '/'));
77+
78+
allRefs = allRefs.concat(schemaRefs);
79+
}
80+
81+
for (const rootSchemaPath of rootSchemaPaths) {
82+
allRefs = allRefs.filter(ref => lowerCaseCompare(ref.split('#')[0], rootSchemaPath) !== 0);
83+
}
84+
85+
return [...new Set(allRefs)];
86+
}
87+
88+
executeSynchronous(async () => {
89+
const rootSchemaRefs = await findAllResourceReferences();
90+
91+
const allResources: { [type: string]: string[] } = {};
92+
for (const ref of rootSchemaRefs) {
93+
const resources = await getResourceInfo(ref);
94+
95+
for (const resource of resources) {
96+
// Casing can vary, so do a case-insensitive lookup
97+
let resourceKey = Object.keys(allResources).find(key => lowerCaseCompare(key, resource.type) === 0);
98+
if (resourceKey === undefined) {
99+
resourceKey = resource.type;
100+
allResources[resourceKey] = [];
101+
}
102+
103+
allResources[resourceKey].push(resource.apiVersion);
104+
}
105+
}
106+
107+
for (const resourceType of Object.keys(allResources)) {
108+
allResources[resourceType].sort();
109+
}
110+
111+
const sortedJsonOutput = JSON.stringify(allResources, Object.keys(allResources).sort(), 2);
112+
await writeFile(resourcesJsonPath, sortedJsonOutput, { encoding: 'utf8' });
113+
});

generator/constants.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
// Licensed under the MIT License.
33
import path from 'path';
44

5-
export const generatorRoot = path.resolve(__dirname, '../');
5+
export const repoRoot = path.resolve(__dirname, '../');
66

77
export const autoRestVerboseOutput = false;
88

99
export const schemasBaseUri = 'https://schema.management.azure.com/schemas';
10-
export const schemasBasePath = path.join(generatorRoot, 'schemas');
10+
export const schemasBasePath = path.join(repoRoot, 'schemas');
11+
export const resourcesJsonPath = path.join(repoRoot, 'generator/resources.json');
1112
export const resourceGroupRootSchema = {
1213
file: path.join(schemasBasePath, 'common/autogeneratedResources.json'),
1314
jsonPath: 'allOf[1].oneOf'

generator/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"scripts": {
1111
"build": "tsc -p .",
1212
"list-basepaths": "ts-node cmd/listbasepaths",
13+
"list-resources": "ts-node cmd/listresources",
1314
"generate-all": "ts-node cmd/generateall",
1415
"find-basepath": "ts-node cmd/findbasepath",
1516
"generate-single": "ts-node cmd/generatesingle",

0 commit comments

Comments
 (0)