Skip to content

Commit e61597f

Browse files
pshao25Pan Shao
andauthored
Support PrivateEndpointConnection as a resource (#5147)
Co-authored-by: Pan Shao <pashao@microsoft.com>
1 parent 8ff0f13 commit e61597f

7 files changed

Lines changed: 127 additions & 116 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@autorest/openapi-to-typespec",
5+
"comment": "Support PrivateEndpointConnection as a resource",
6+
"type": "patch"
7+
}
8+
],
9+
"packageName": "@autorest/openapi-to-typespec"
10+
}

packages/extensions/openapi-to-typespec/src/generate/generate-arm-resource.ts

Lines changed: 60 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ function generateArmResourceModel(resource: TspArmResource): string {
6161
const doc = generateDocs(resource);
6262
definitions.push(doc);
6363

64+
if (resource.resourceKind === "PrivateEndpointConnectionResource") {
65+
definitions.push(`model PrivateEndpointConnection is PrivateEndpointConnectionResource;`);
66+
definitions.push(`alias PrivateEndpointOperations = PrivateEndpoints<PrivateEndpointConnection>;`);
67+
return definitions.join("\n");
68+
}
69+
6470
const decorators = generateDecorators(resource.decorators);
6571
decorators && definitions.push(decorators);
6672

@@ -91,13 +97,16 @@ function generateArmResourceOperationGroups(resource: TspArmResource): string {
9197
const definitions: string[] = [];
9298

9399
for (const operationGroup of resource.resourceOperationGroups) {
94-
definitions.push(generateArmResourceOperationGroup(operationGroup));
100+
definitions.push(generateArmResourceOperationGroup(operationGroup, resource));
95101
}
96102

97103
return definitions.join("\n");
98104
}
99105

100-
function generateArmResourceOperationGroup(operationGroup: TspArmResourceOperationGroup): string {
106+
function generateArmResourceOperationGroup(
107+
operationGroup: TspArmResourceOperationGroup,
108+
resource: TspArmResource,
109+
): string {
101110
const { isFullCompatible } = getOptions();
102111

103112
const definitions: string[] = [];
@@ -138,10 +147,10 @@ function generateArmResourceOperationGroup(operationGroup: TspArmResourceOperati
138147

139148
const operationKind = operationGroup.isLegacy
140149
? `${operationGroup.legacyOperationGroup!.interfaceName}.${getLegacyOperationKind(operation.kind)}`
141-
: getOperationKind(operation);
150+
: getOperationKind(operation, resource);
142151
if (operation.kind === "ArmResourceActionSync" || operation.kind === "ArmResourceActionAsync") {
143152
definitions.push(
144-
`${operation.name} is ${operationKind}<${operation.targetResource ? `${operation.targetResource}, ` : ""}${operation.resource}, ${generateArmRequest(
153+
`${operation.name} is ${operationKind}<${getSpecialParameter(operation, resource)}${operation.resource}, ${generateArmRequest(
145154
operation.request,
146155
)}, ${generateArmResponse(operation.response)}${
147156
operation.baseParameters && !operationGroup.isLegacy
@@ -153,15 +162,15 @@ function generateArmResourceOperationGroup(operationGroup: TspArmResourceOperati
153162
);
154163
} else if (operation.kind === "ArmResourceActionAsyncBase") {
155164
definitions.push(
156-
`${operation.name} is ${operationKind}<${operation.targetResource ? `${operation.targetResource}, ` : ""}${operation.resource}, ${generateArmRequest(
165+
`${operation.name} is ${operationKind}<${getSpecialParameter(operation, resource)}${operation.resource}, ${generateArmRequest(
157166
operation.request,
158167
)}, ${generateArmResponse(operation.response)}, BaseParameters = ${operation.baseParameters![0]}${
159168
operation.parameters ? `, Parameters = { ${generateParameters(operation.parameters)} }` : ""
160169
}${operation.optionalRequestBody === true ? `, OptionalRequestBody = true` : ""}>;`,
161170
);
162171
} else {
163172
definitions.push(
164-
`${operation.name} is ${operationKind}<${operation.targetResource ? `${operation.targetResource}, ` : ""}${operation.resource}${
173+
`${operation.name} is ${operationKind}<${getSpecialParameter(operation, resource)}${operation.resource}${
165174
operation.patchModel ? `, PatchModel = ${operation.patchModel}` : ""
166175
}${
167176
operation.baseParameters && !operationGroup.isLegacy
@@ -187,55 +196,49 @@ function isPatchWithOptionalBody(operation: TspArmResourceOperation): boolean {
187196
);
188197
}
189198

190-
function getOperationKind(operation: TspArmResourceOperation): string {
199+
// These templates have special parameter as the first parameter
200+
// - Extension operations
201+
// - PrivateEndpointConnection operations
202+
function getSpecialParameter(operation: TspArmResourceOperation, resource: TspArmResource): string {
203+
if (operation.targetResource) return `${operation.targetResource}, `;
204+
if (resource.resourceKind === "PrivateEndpointConnectionResource") return `${resource.resourceParent!.name}, `;
205+
return "";
206+
}
207+
208+
function getOperationKind(operation: TspArmResourceOperation, resource: TspArmResource): string {
209+
if (resource.resourceKind === "PrivateEndpointConnectionResource")
210+
return `PrivateEndpointOperations.${getPrivateEndpointConnectionOperationKind(operation.kind)}`;
191211
if (operation.targetResource) return `Extension.${getExtensionOperationKind(operation.kind)}`;
192212
if (isPatchWithOptionalBody(operation)) return `Azure.ResourceManager.Legacy.${operation.kind.replace("Arm", "")}`;
193213
return operation.kind;
194214
}
195215

216+
function getPrivateEndpointConnectionOperationKind(kind: TspArmOperationType): string {
217+
switch (kind) {
218+
case "ArmResourceListByParent":
219+
return "ListByParent";
220+
default:
221+
return getOperationBaseKind(kind);
222+
}
223+
}
224+
196225
function getExtensionOperationKind(kind: TspArmOperationType): string {
197226
switch (kind) {
198-
case "ArmResourceRead":
199-
return "Read";
200-
case "ArmResourceCheckExistence":
201-
return "CheckExistence";
202-
case "ArmResourceCreateOrReplaceSync":
203-
return "CreateOrReplaceSync";
204-
case "ArmResourceCreateOrReplaceAsync":
205-
return "CreateOrReplaceAsync";
206-
case "ArmResourcePatchSync":
207-
return "CustomPatchSync";
208-
case "ArmResourcePatchAsync":
209-
return "CustomPatchAsync";
210-
case "ArmCustomPatchSync":
211-
return "CustomPatchSync";
212-
case "ArmCustomPatchAsync":
213-
return "CustomPatchAsync";
214-
case "ArmResourceDeleteSync":
215-
return "DeleteSync";
216227
case "ArmResourceDeleteWithoutOkAsync":
217228
return "DeleteWithoutOkAsync";
218-
case "ArmResourceActionSync":
219-
return "ActionSync";
220-
case "ArmResourceActionAsync":
221-
return "ActionAsync";
222-
case "ArmResourceActionAsyncBase":
223-
return "ActionAsyncBase";
224229
case "ArmResourceListByParent":
225230
return "ListByTarget";
226231
case "ArmListBySubscription":
227232
return "List";
228233
case "ArmResourceListAtScope":
229234
return "List";
235+
default:
236+
return getOperationBaseKind(kind);
230237
}
231238
}
232239

233240
function getLegacyOperationKind(kind: TspArmOperationType): string {
234241
switch (kind) {
235-
case "ArmResourceRead":
236-
return "Read";
237-
case "ArmResourceCheckExistence":
238-
return "CheckExistence";
239242
case "ArmResourceCreateOrReplaceSync":
240243
return "CreateOrUpdateSync";
241244
case "ArmResourceCreateOrReplaceAsync":
@@ -244,14 +247,35 @@ function getLegacyOperationKind(kind: TspArmOperationType): string {
244247
return "PatchSync";
245248
case "ArmResourcePatchAsync":
246249
return "PatchAsync";
250+
case "ArmResourceDeleteWithoutOkAsync":
251+
return "DeleteWithoutOkAsync";
252+
default:
253+
return getOperationBaseKind(kind);
254+
}
255+
}
256+
257+
function getOperationBaseKind(kind: TspArmOperationType): string {
258+
switch (kind) {
259+
case "ArmResourceRead":
260+
return "Read";
261+
case "ArmResourceCheckExistence":
262+
return "CheckExistence";
263+
case "ArmResourceCreateOrReplaceSync":
264+
return "CreateOrReplaceSync";
265+
case "ArmResourceCreateOrReplaceAsync":
266+
return "CreateOrReplaceAsync";
267+
case "ArmResourcePatchSync":
268+
return "CustomPatchSync";
269+
case "ArmResourcePatchAsync":
270+
return "CustomPatchAsync";
247271
case "ArmCustomPatchSync":
248272
return "CustomPatchSync";
249273
case "ArmCustomPatchAsync":
250274
return "CustomPatchAsync";
251275
case "ArmResourceDeleteSync":
252276
return "DeleteSync";
253277
case "ArmResourceDeleteWithoutOkAsync":
254-
return "DeleteWithoutOkAsync";
278+
return "DeleteAsync";
255279
case "ArmResourceActionSync":
256280
return "ActionSync";
257281
case "ArmResourceActionAsync":

packages/extensions/openapi-to-typespec/src/interfaces.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,8 @@ export type ArmResourceKind =
232232
| "TrackedResource"
233233
| "ProxyResource"
234234
| "ExtensionResource"
235-
| "Legacy.TrackedResourceWithOptionalLocation";
235+
| "Legacy.TrackedResourceWithOptionalLocation"
236+
| "PrivateEndpointConnectionResource";
236237
export type ArmResourceOperationKind = "TrackedResourceOperations" | "ProxyResourceOperations";
237238

238239
const FIRST_LEVEL_RESOURCE = [

packages/extensions/openapi-to-typespec/src/transforms/transform-arm-resources.ts

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Operation, Parameter, Property, SchemaType } from "@autorest/codemodel"
22
import { capitalize } from "@azure-tools/codegen";
33
import _ from "lodash";
44
import { singular } from "pluralize";
5-
import { getSession } from "../autorest-session";
5+
import { getSession, isCommonTypeModel } from "../autorest-session";
66
import { getDataTypes } from "../data-types";
77
import {
88
ArmResourceKind,
@@ -114,8 +114,10 @@ export function transformTspArmResource(schema: ArmResourceSchema): TspArmResour
114114

115115
const clientDecorators = buildResourceClientDecorators(schema);
116116
const keyProperty = buildKeyProperty(schema);
117-
const augmentDecorators = buildKeyAugmentDecorators(schema, keyProperty) ?? [];
118-
const properties = [keyProperty, ...getOtherProperties(schema, augmentDecorators)];
117+
const resourceParent = getParentResource(schema);
118+
const resourceKind = getResourceKind(schema, resourceParent);
119+
const augmentDecorators = buildKeyAugmentDecorators(schema, keyProperty, resourceKind) ?? [];
120+
const properties = [keyProperty, ...getOtherProperties(schema, resourceKind)];
119121

120122
if (propertiesModel) {
121123
augmentDecorators.push(...buildPropertiesAugmentDecorators(schema, propertiesModel));
@@ -136,9 +138,9 @@ export function transformTspArmResource(schema: ArmResourceSchema): TspArmResour
136138
kind: "ArmResource",
137139
name: schema.resourceMetadata[0].SwaggerModelName,
138140
fixMe,
139-
resourceKind: getResourceKind(schema),
141+
resourceKind,
140142
properties,
141-
resourceParent: getParentResource(schema),
143+
resourceParent,
142144
propertiesModelName,
143145
propertiesPropertyRequired,
144146
propertiesPropertyDescription,
@@ -951,10 +953,9 @@ function isSameResponse(actual: TypespecTemplateModel, expected: TypespecTemplat
951953

952954
function getOtherProperties(
953955
schema: ArmResourceSchema,
954-
augmentDecorators: TypespecDecorator[],
956+
resourceKind: ArmResourceKind,
955957
): (TypespecObjectProperty | TypespecSpreadStatement)[] {
956958
const knownProperties = ["properties", "name", "id", "type", "systemData"];
957-
const resourceKind = getResourceKind(schema);
958959
if (resourceKind === "TrackedResource" || resourceKind === "Legacy.TrackedResourceWithOptionalLocation") {
959960
knownProperties.push(...["location", "tags"]);
960961
}
@@ -1255,7 +1256,13 @@ function getParentResource(schema: ArmResourceSchema): TspArmResource | undefine
12551256
}
12561257
}
12571258

1258-
function getResourceKind(schema: ArmResourceSchema): ArmResourceKind {
1259+
function getResourceKind(schema: ArmResourceSchema, resourceParent: TspArmResource | undefined): ArmResourceKind {
1260+
if (schema.language.default.name === "PrivateEndpointConnection" && isCommonTypeModel(schema.language.default.name)) {
1261+
if (resourceParent === undefined) {
1262+
logger().warning(`PrivateEndpointConnection resource is missing parent resource. Change to normal resource.`);
1263+
} else return "PrivateEndpointConnectionResource";
1264+
}
1265+
12591266
if (schema.resourceMetadata[0].ScopeType === "Scope") {
12601267
return "ExtensionResource";
12611268
}
@@ -1274,6 +1281,7 @@ function getResourceKind(schema: ArmResourceSchema): ArmResourceKind {
12741281
function buildKeyAugmentDecorators(
12751282
schema: ArmResourceSchema,
12761283
keyProperty: TypespecSpreadStatement,
1284+
resourceKind: ArmResourceKind,
12771285
): TypespecDecorator[] {
12781286
return (
12791287
keyProperty.decorators
@@ -1283,11 +1291,15 @@ function buildKeyAugmentDecorators(
12831291
d.target = `${schema.resourceMetadata[0].SwaggerModelName}.name`;
12841292
return d;
12851293
}) ?? []
1286-
).concat({
1287-
name: "doc",
1288-
target: `${schema.resourceMetadata[0].SwaggerModelName}.name`,
1289-
arguments: [generateDocsContent(keyProperty)],
1290-
});
1294+
).concat(
1295+
resourceKind !== "PrivateEndpointConnectionResource"
1296+
? {
1297+
name: "doc",
1298+
target: `${schema.resourceMetadata[0].SwaggerModelName}.name`,
1299+
arguments: [generateDocsContent(keyProperty)],
1300+
}
1301+
: [],
1302+
);
12911303
}
12921304

12931305
function buildPropertiesAugmentDecorators(schema: ArmResourceSchema, propertiesModel: Property): TypespecDecorator[] {

packages/extensions/openapi-to-typespec/test/arm-agrifood/swagger-output/swagger.json

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,18 +1387,14 @@
13871387
"pattern": "^[A-Za-z0-9]+(-[A-Za-z0-9]+)*$"
13881388
},
13891389
{
1390-
"name": "privateEndpointConnectionName",
1391-
"in": "path",
1392-
"description": "Private endpoint connection name.",
1393-
"required": true,
1394-
"type": "string"
1390+
"$ref": "../../common-types/resource-management/v4/privatelinks.json#/parameters/PrivateEndpointConnectionName"
13951391
}
13961392
],
13971393
"responses": {
13981394
"200": {
13991395
"description": "Azure operation completed successfully.",
14001396
"schema": {
1401-
"$ref": "#/definitions/PrivateEndpointConnection"
1397+
"$ref": "../../common-types/resource-management/v4/privatelinks.json#/definitions/PrivateEndpointConnection"
14021398
}
14031399
},
14041400
"default": {
@@ -1441,19 +1437,15 @@
14411437
"pattern": "^[A-Za-z0-9]+(-[A-Za-z0-9]+)*$"
14421438
},
14431439
{
1444-
"name": "privateEndpointConnectionName",
1445-
"in": "path",
1446-
"description": "Private endpoint connection name.",
1447-
"required": true,
1448-
"type": "string"
1440+
"$ref": "../../common-types/resource-management/v4/privatelinks.json#/parameters/PrivateEndpointConnectionName"
14491441
},
14501442
{
14511443
"name": "request",
14521444
"in": "body",
14531445
"description": "Request object.",
14541446
"required": true,
14551447
"schema": {
1456-
"$ref": "#/definitions/PrivateEndpointConnection"
1448+
"$ref": "../../common-types/resource-management/v4/privatelinks.json#/definitions/PrivateEndpointConnection"
14571449
}
14581450
}
14591451
],
@@ -1504,11 +1496,7 @@
15041496
"pattern": "^[A-Za-z0-9]+(-[A-Za-z0-9]+)*$"
15051497
},
15061498
{
1507-
"name": "privateEndpointConnectionName",
1508-
"in": "path",
1509-
"description": "Private endpoint connection name.",
1510-
"required": true,
1511-
"type": "string"
1499+
"$ref": "../../common-types/resource-management/v4/privatelinks.json#/parameters/PrivateEndpointConnectionName"
15121500
}
15131501
],
15141502
"responses": {
@@ -2338,7 +2326,7 @@
23382326
"type": "array",
23392327
"description": "Private endpoints.",
23402328
"items": {
2341-
"$ref": "#/definitions/PrivateEndpointConnection"
2329+
"$ref": "../../common-types/resource-management/v4/privatelinks.json#/definitions/PrivateEndpointConnection"
23422330
},
23432331
"readOnly": true
23442332
}
@@ -2692,22 +2680,6 @@
26922680
],
26932681
"x-ms-discriminator-value": "OAuthClientCredentials"
26942682
},
2695-
"PrivateEndpointConnection": {
2696-
"type": "object",
2697-
"description": "The private endpoint connection resource.",
2698-
"properties": {
2699-
"properties": {
2700-
"$ref": "../../common-types/resource-management/v4/privatelinks.json#/definitions/PrivateEndpointConnectionProperties",
2701-
"description": "Resource properties.",
2702-
"x-ms-client-flatten": true
2703-
}
2704-
},
2705-
"allOf": [
2706-
{
2707-
"$ref": "../../common-types/resource-management/v4/types.json#/definitions/ProxyResource"
2708-
}
2709-
]
2710-
},
27112683
"PrivateLinkResource": {
27122684
"type": "object",
27132685
"description": "A private link resource.",

0 commit comments

Comments
 (0)