From 2df12dde2a2be1120efc3e7052373e0b1b0e967d Mon Sep 17 00:00:00 2001 From: Brett DeFoy Date: Tue, 2 May 2023 11:02:47 -0700 Subject: [PATCH] WIP fix rule --- docs/resource-must-reference-common-types.md | 10 + .../resource-must-reference-common-types.ts | 2 +- ...must-reference-common-types-test-data.json | 834 +++++++++++++++ ...source-must-reference-common-types.test.ts | 966 ++++++++++++++++-- 4 files changed, 1732 insertions(+), 80 deletions(-) create mode 100644 packages/rulesets/src/spectral/test/resource-must-reference-common-types-test-data.json diff --git a/docs/resource-must-reference-common-types.md b/docs/resource-must-reference-common-types.md index cc161babb..e1fe9c241 100644 --- a/docs/resource-must-reference-common-types.md +++ b/docs/resource-must-reference-common-types.md @@ -15,3 +15,13 @@ Validates that any resource definitions use the definitions for ProxyResource or ## How to fix the violation Ensure that all resource definitions reference the ProxyResource or TrackedResource definitions in the common types. + +E.g., + +```json +"allOf": [ +  { +    "$ref": "../../../../../common-types/resource-management/v2/types.json#/definitions/ProxyResource" +  } +], +``` diff --git a/packages/rulesets/src/spectral/functions/resource-must-reference-common-types.ts b/packages/rulesets/src/spectral/functions/resource-must-reference-common-types.ts index b68c23305..bca6d5763 100644 --- a/packages/rulesets/src/spectral/functions/resource-must-reference-common-types.ts +++ b/packages/rulesets/src/spectral/functions/resource-must-reference-common-types.ts @@ -20,7 +20,7 @@ export const resourceMustReferenceCommonTypes = (ref: any, _opts: any, ctx: any) // get the resource name using the last word of the ref path const resourceName = ref.toString().split("/").pop() // find the resource definition by name, get the references under it - const allOfRef = definitions[resourceName]?.properties?.allOf + const allOfRef = definitions[resourceName]?.allOf const path = ["definitions", resourceName] const error = [ { diff --git a/packages/rulesets/src/spectral/test/resource-must-reference-common-types-test-data.json b/packages/rulesets/src/spectral/test/resource-must-reference-common-types-test-data.json new file mode 100644 index 000000000..b751a4a4e --- /dev/null +++ b/packages/rulesets/src/spectral/test/resource-must-reference-common-types-test-data.json @@ -0,0 +1,834 @@ +{ + "swagger": "2.0", + "info": { + "title": "ResourcePrivateLinkClient", + "version": "2023-03-01-preview", + "description": "Provides operations for managing private link resources" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/providers/Microsoft.Management/managementGroups/{groupId}/providers/Microsoft.Authorization/privateLinkAssociations/{plaId}": { + "put": { + "tags": [ + "PrivateLinkAssociation" + ], + "operationId": "PrivateLinkAssociation_Put", + "description": "Create a PrivateLinkAssociation", + "parameters": [ + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/GroupIdParameter" + }, + { + "$ref": "#/parameters/PrivateLinkAssociationIdParameter" + }, + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/PrivateLinkAssociationObject" + }, + "description": "Parameters supplied to create the private link association." + } + ], + "responses": { + "200": { + "description": "Ok - Returns information about the new private link association.", + "schema": { + "$ref": "#/definitions/PrivateLinkAssociation" + } + }, + "201": { + "description": "Created - Returns information about the new private link association.", + "schema": { + "$ref": "#/definitions/PrivateLinkAssociation" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + }, + "x-ms-examples": { + "Create a private link association, associate scope to rmpl.": { + "$ref": "./examples/PutPrivateLinkAssociation.json" + } + } + }, + "get": { + "tags": [ + "PrivateLinkAssociation" + ], + "operationId": "PrivateLinkAssociation_Get", + "description": "Get a single private link association", + "parameters": [ + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/GroupIdParameter" + }, + { + "$ref": "#/parameters/PrivateLinkAssociationIdParameter" + } + ], + "responses": { + "200": { + "description": "Ok. The request has succeeded", + "schema": { + "$ref": "#/definitions/PrivateLinkAssociation" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + }, + "x-ms-examples": { + "Get a single private link association.": { + "$ref": "./examples/GetPrivateLinkAssociation.json" + } + } + }, + "delete": { + "tags": [ + "PrivateLinkAssociation" + ], + "operationId": "PrivateLinkAssociation_Delete", + "description": "Delete a PrivateLinkAssociation", + "parameters": [ + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/GroupIdParameter" + }, + { + "$ref": "#/parameters/PrivateLinkAssociationIdParameter" + } + ], + "responses": { + "200": { + "description": "OK" + }, + "204": { + "description": "" + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + }, + "x-ms-examples": { + "Delete a private link association.": { + "$ref": "./examples/DeletePrivateLinkAssociation.json" + } + } + } + }, + "/providers/Microsoft.Management/managementGroups/{groupId}/providers/Microsoft.Authorization/privateLinkAssociations": { + "get": { + "tags": [ + "PrivateLinkAssociation" + ], + "operationId": "PrivateLinkAssociation_List", + "description": "Get a private link association for a management group scope", + "parameters": [ + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/GroupIdParameter" + } + ], + "responses": { + "200": { + "description": "Ok. The request has succeeded", + "schema": { + "$ref": "#/definitions/PrivateLinkAssociationGetResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + }, + "x-ms-examples": { + "Get a private link association for a MG scope.": { + "$ref": "./examples/ListPrivateLinkAssociation.json" + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Authorization/resourceManagementPrivateLinks/{rmplName}": { + "put": { + "tags": [ + "ResourceManagementPrivateLink" + ], + "operationId": "ResourceManagementPrivateLink_Put", + "description": "Create a resource management group private link.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group. The name is case insensitive.", + "minLength": 1, + "maxLength": 90 + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ResourceManagementPrivateLinkParameter" + }, + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/ResourceManagementPrivateLinkLocation" + }, + "description": "The region to create the Resource Management private link." + } + ], + "responses": { + "200": { + "description": "OK. Returns information about the Resource Management Private Link.", + "schema": { + "$ref": "#/definitions/ResourceManagementPrivateLink" + } + }, + "201": { + "description": "Created. Returns information about the Resource Management Private Link.", + "schema": { + "$ref": "#/definitions/ResourceManagementPrivateLink" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + }, + "x-ms-examples": { + "Create Resource Management Private Link.": { + "$ref": "./examples/PutResourceManagementPrivateLink.json" + } + } + }, + "get": { + "tags": [ + "ResourceManagementPrivateLink" + ], + "operationId": "ResourceManagementPrivateLink_Get", + "description": "Get a resource management private link(resource-level).", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group. The name is case insensitive.", + "minLength": 1, + "maxLength": 90 + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ResourceManagementPrivateLinkParameter" + } + ], + "responses": { + "200": { + "description": "Ok. Returns information about the resource management private link.", + "schema": { + "$ref": "#/definitions/ResourceManagementPrivateLink" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + }, + "x-ms-examples": { + "Get a Resource Management Private Link(resource-level).": { + "$ref": "./examples/GetResourceManagementPrivateLink.json" + } + } + }, + "patch": { + "tags": [ + "ResourceManagementPrivateLink" + ], + "operationId": "ResourceManagementPrivateLink_Update", + "description": "Update a resource management private link.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group. The name is case insensitive.", + "minLength": 1, + "maxLength": 90 + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ResourceManagementPrivateLinkParameter" + }, + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/ResourceManagementPrivateLinkPatch" + }, + "description": "Patch parameters for Resource Management private link." + } + ], + "responses": { + "200": { + "description": "OK. Returns information about the Resource Management Private Link.", + "schema": { + "$ref": "#/definitions/ResourceManagementPrivateLink" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + }, + "x-ms-examples": { + "Update Resource Management Private Link.": { + "$ref": "./examples/PatchResourceManagementPrivateLink.json" + } + } + }, + "delete": { + "tags": [ + "ResourceManagementPrivateLink" + ], + "operationId": "ResourceManagementPrivateLink_Delete", + "description": "Delete a resource management private link.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group. The name is case insensitive.", + "minLength": 1, + "maxLength": 90 + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ResourceManagementPrivateLinkParameter" + } + ], + "responses": { + "200": { + "description": "OK" + }, + "204": { + "description": "" + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + }, + "x-ms-examples": { + "Delete a Resource Management Private Link.": { + "$ref": "./examples/DeleteResourceManagementPrivateLink.json" + } + } + } + }, + "/subscriptions/{subscriptionId}/providers/Microsoft.Authorization/resourceManagementPrivateLinks": { + "get": { + "tags": [ + "ResourceManagementPrivateLink" + ], + "operationId": "ResourceManagementPrivateLink_List", + "description": "Get all the resource management private links in a subscription.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Ok - Returns an array of private links.", + "schema": { + "$ref": "#/definitions/ResourceManagementPrivateLinkListResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + }, + "x-ms-examples": { + "Delete a Resource Management Private Link.": { + "$ref": "./examples/ListSubscriptionResourceManagementPrivateLink.json" + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Authorization/resourceManagementPrivateLinks": { + "get": { + "tags": [ + "ResourceManagementPrivateLink" + ], + "operationId": "ResourceManagementPrivateLink_ListByResourceGroup", + "description": "Get all the resource management private links in a resource group.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group. The name is case insensitive.", + "minLength": 1, + "maxLength": 90 + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Ok - Returns an array of private links.", + "schema": { + "$ref": "#/definitions/ResourceManagementPrivateLinkListResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + }, + "x-ms-examples": { + "Delete a Resource Management Private Link.": { + "$ref": "./examples/ListResourceGroupResourceManagementPrivateLink.json" + } + } + } + }, + "/providers/Microsoft.Authorization/enablePrivateLinkNetworkAccess": { + "post": { + "tags": [ + "EnablePrivateLinkNetworkAccess" + ], + "operationId": "EnablePrivateLinkNetworkAccess_Post", + "description": "Enable private link network access for global administrator", + "parameters": [ + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/EnablePrivateLinkNetworkAccessObject" + }, + "description": "Parameters supplied to enable private link network access." + } + ], + "responses": { + "200": { + "description": "Post Succeed." + }, + "202": { + "description": "Accepted - Returns an Azure async operation header with HttpStatusCode 202.", + "headers": { + "Azure-AsyncOperation": { + "type": "string" + }, + "Location": { + "type": "string" + } + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + }, + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "Enable a private link network access.": { + "$ref": "./examples/PostEnablePrivateLinkNetworkAccess.json" + } + } + } + }, + "/providers/Microsoft.Authorization/operations": { + "get": { + "tags": [ + "Operations" + ], + "operationId": "AuthorizationOperations_List", + "description": "Lists all of the available Microsoft.Authorization REST API operations.", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/definitions/OperationListResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + }, + "x-ms-examples": { + "List provider operations": { + "$ref": "./examples/ListProviderOperations.json" + } + } + } + } + }, + "definitions": { + "PrivateLinkAssociationObject": { + "type": "object", + "properties": { + "properties": { + "$ref": "#/definitions/PrivateLinkAssociationProperties", + "description": "The properties of the PrivateLinkAssociation." + } + } + }, + "EnablePrivateLinkNetworkAccessObject": { + "type": "object", + "properties": { + "scope": { + "type": "string", + "description": "The scope of private link associations where network access is updated." + } + } + }, + "PrivateLinkAssociationProperties": { + "type": "object", + "properties": { + "privateLink": { + "type": "string", + "description": "The rmpl Resource ID." + }, + "publicNetworkAccess": { + "type": "string", + "enum": [ + "Enabled", + "Disabled" + ], + "x-ms-enum": { + "name": "publicNetworkAccessOptions", + "modelAsString": true + } + } + } + }, + "PrivateLinkAssociationGetResult": { + "description": "Result of the request to get PLA for a MG scope. ", + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/PrivateLinkAssociation" + }, + "description": "private link association information." + } + } + }, + "PrivateLinkAssociationPropertiesExpanded": { + "type": "object", + "properties": { + "privateLink": { + "type": "string", + "description": "The rmpl Resource ID." + }, + "publicNetworkAccess": { + "type": "string", + "enum": [ + "Enabled", + "Disabled" + ], + "x-ms-enum": { + "name": "publicNetworkAccessOptions", + "modelAsString": true + } + }, + "tenantID": { + "type": "string", + "description": "The TenantID." + }, + "scope": { + "type": "string", + "description": "The scope of the private link association." + } + }, + "description": "Private Link Association Properties." + }, + "PrivateLinkAssociation": { + "type": "object", + "allOf": [ + { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/definitions/ProxyResource" + } + ], + "properties": { + "properties": { + "$ref": "#/definitions/PrivateLinkAssociationPropertiesExpanded", + "description": "The private link association properties." + }, + "id": { + "readOnly": true, + "type": "string", + "description": "The plaResourceID." + }, + "type": { + "readOnly": true, + "type": "string", + "description": "The operation type." + }, + "name": { + "readOnly": true, + "type": "string", + "description": "The pla name." + } + } + }, + "ResourceManagementPrivateLink": { + "type": "object", + "allOf": [ + { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/definitions/ProxyResource" + } + ], + "properties": { + "properties": { + "$ref": "#/definitions/ResourceManagementPrivateLinkEndpointConnections" + }, + "id": { + "readOnly": true, + "type": "string", + "description": "The rmplResourceID." + }, + "name": { + "readOnly": true, + "type": "string", + "description": "The rmpl Name." + }, + "type": { + "readOnly": true, + "type": "string", + "description": "The operation type." + }, + "location": { + "type": "string", + "description": "the region of the rmpl" + }, + "tags": { + "description": "The resource tags.", + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "x-ms-azure-resource": true + }, + "ResourceManagementPrivateLinkLocation": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "the region to create private link association." + } + } + }, + "ResourceManagementPrivateLinkPatch": { + "type": "object", + "properties": { + "tags": { + "description": "Resource tags.", + "type": "object", + "additionalProperties": { + "type": "string", + "x-nullable": true + } + } + } + }, + "ResourceManagementPrivateLinkEndpointConnections": { + "type": "object", + "properties": { + "privateEndpointConnections": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The private endpoint connections." + } + } + }, + "ResourceManagementPrivateLinkListResult": { + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/ResourceManagementPrivateLink" + }, + "description": "An array of resource management private links." + } + } + }, + "CloudError": { + "x-ms-external": true, + "type": "object", + "properties": { + "error": { + "$ref": "../../../../../common-types/resource-management/v1/types.json#/definitions/ErrorResponse" + } + }, + "description": "An error response for a resource management request." + } + }, + "parameters": { + "ApiVersionParameter": { + "name": "api-version", + "in": "query", + "required": true, + "type": "string", + "description": "The API version to use for this operation.", + "x-ms-parameter-location": "client" + }, + "GroupIdParameter": { + "name": "groupId", + "in": "path", + "required": true, + "type": "string", + "description": "The management group ID.", + "x-ms-parameter-location": "method", + "minLength": 1, + "maxLength": 90 + }, + "SubscriptionIdParameter": { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the target subscription.", + "x-ms-parameter-location": "method" + }, + "PrivateLinkAssociationIdParameter": { + "name": "plaId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the PLA", + "x-ms-parameter-location": "method" + }, + "ResourceManagementPrivateLinkParameter": { + "name": "rmplName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource management private link.", + "x-ms-parameter-location": "method" + } + } +} \ No newline at end of file diff --git a/packages/rulesets/src/spectral/test/resource-must-reference-common-types.test.ts b/packages/rulesets/src/spectral/test/resource-must-reference-common-types.test.ts index 464c0ca42..248080f31 100644 --- a/packages/rulesets/src/spectral/test/resource-must-reference-common-types.test.ts +++ b/packages/rulesets/src/spectral/test/resource-must-reference-common-types.test.ts @@ -9,136 +9,944 @@ beforeAll(async () => { return nonResolvingLinter }) -test(`${RULE} should find errors`, async () => { - const oasDoc = { - swagger: "2.0", - paths: { - "/providers/Microsoft.Bakery/breads/{breadName}": { - get: { - responses: { - 200: { - description: "a response", - schema: { - $ref: "#/definitions/Bread", - }, +// TODO: uncomment +// test(`${RULE} should find errors`, async () => { +// const oasDoc = { +// swagger: "2.0", +// paths: { +// "/providers/Microsoft.Bakery/breads/{breadName}": { +// get: { +// responses: { +// 200: { +// description: "a response", +// schema: { +// $ref: "#/definitions/Bread", +// }, +// }, +// }, +// }, +// put: { +// responses: { +// 200: { +// description: "a response", +// schema: { +// $ref: "#/definitions/Bread", +// }, +// }, +// }, +// }, +// }, +// }, +// definitions: { +// Bread: { +// type: "object", +// properties: { +// name: { +// description: "bread name", +// type: "string", +// }, +// }, +// }, +// }, +// } + +// return nonResolvingLinter.run(oasDoc).then((results) => { +// expect(results.length).toBe(1) +// expect(results[0].message).toBe( +// "Resource definition 'Bread' must reference the common types resource definition for ProxyResource or TrackedResource." +// ) +// }) +// }) + +// test(`${RULE} should find no errors`, async () => { +// const oasDoc = { +// swagger: "2.0", +// paths: { +// "/providers/Microsoft.Bakery/breads/{breadName}": { +// get: { +// responses: { +// 200: { +// description: "a response", +// schema: { +// $ref: "#/definitions/Bread", +// }, +// }, +// }, +// }, +// put: { +// responses: { +// 200: { +// description: "a response", +// schema: { +// $ref: "#/definitions/Bread", +// }, +// }, +// }, +// }, +// }, +// }, +// "/providers/Microsoft.Bakery/cookies/{cookieName}": { +// get: { +// responses: { +// 200: { +// description: "a response", +// schema: { +// $ref: "#/definitions/Cookie", +// }, +// }, +// }, +// }, +// put: { +// responses: { +// 200: { +// description: "a response", +// schema: { +// $ref: "#/definitions/Cookie", +// }, +// }, +// }, +// }, +// }, +// definitions: { +// Bread: { +// type: "object", +// properties: { +// name: { +// description: "bread name", +// type: "string", +// }, +// allOf: [ +// { +// $ref: "../../../../../common-types/resource-management/v1/types.json#/definitions/ProxyResource", +// }, +// ], +// }, +// }, +// }, +// Cookie: { +// type: "object", +// properties: { +// name: { +// description: "cookie name", +// type: "string", +// }, +// allOf: [ +// { +// $ref: "../../../../../common-types/resource-management/v1/types.json#/definitions/TrackedResource", +// }, +// ], +// }, +// }, +// } + +// return nonResolvingLinter.run(oasDoc).then((results) => { +// expect(results.length).toBe(0) +// }) +// }) + +test(`${RULE} should find no errors`, async () => { + // TODO: fix support for PrivateLinkAssociationGetResult + const oasDoc = testData + + return nonResolvingLinter.run(oasDoc).then((results) => { + expect(results.length).toBe(0) + }) +}) + +const testData = { + swagger: "2.0", + info: { + title: "ResourcePrivateLinkClient", + version: "2023-03-01-preview", + description: "Provides operations for managing private link resources", + }, + host: "management.azure.com", + schemes: ["https"], + consumes: ["application/json"], + produces: ["application/json"], + security: [ + { + azure_auth: ["user_impersonation"], + }, + ], + securityDefinitions: { + azure_auth: { + type: "oauth2", + authorizationUrl: "https://login.microsoftonline.com/common/oauth2/authorize", + flow: "implicit", + description: "Azure Active Directory OAuth2 Flow", + scopes: { + user_impersonation: "impersonate your user account", + }, + }, + }, + paths: { + "/providers/Microsoft.Management/managementGroups/{groupId}/providers/Microsoft.Authorization/privateLinkAssociations/{plaId}": { + put: { + tags: ["PrivateLinkAssociation"], + operationId: "PrivateLinkAssociation_Put", + description: "Create a PrivateLinkAssociation", + parameters: [ + { + $ref: "#/parameters/ApiVersionParameter", + }, + { + $ref: "#/parameters/GroupIdParameter", + }, + { + $ref: "#/parameters/PrivateLinkAssociationIdParameter", + }, + { + name: "parameters", + in: "body", + required: true, + schema: { + $ref: "#/definitions/PrivateLinkAssociationObject", + }, + description: "Parameters supplied to create the private link association.", + }, + ], + responses: { + "200": { + description: "Ok - Returns information about the new private link association.", + schema: { + $ref: "#/definitions/PrivateLinkAssociation", + }, + }, + "201": { + description: "Created - Returns information about the new private link association.", + schema: { + $ref: "#/definitions/PrivateLinkAssociation", + }, + }, + default: { + description: "Error response describing why the operation failed.", + schema: { + $ref: "#/definitions/CloudError", }, }, }, - put: { - responses: { - 200: { - description: "a response", - schema: { - $ref: "#/definitions/Bread", - }, + "x-ms-examples": { + "Create a private link association, associate scope to rmpl.": { + $ref: "./examples/PutPrivateLinkAssociation.json", + }, + }, + }, + get: { + tags: ["PrivateLinkAssociation"], + operationId: "PrivateLinkAssociation_Get", + description: "Get a single private link association", + parameters: [ + { + $ref: "#/parameters/ApiVersionParameter", + }, + { + $ref: "#/parameters/GroupIdParameter", + }, + { + $ref: "#/parameters/PrivateLinkAssociationIdParameter", + }, + ], + responses: { + "200": { + description: "Ok. The request has succeeded", + schema: { + $ref: "#/definitions/PrivateLinkAssociation", + }, + }, + default: { + description: "Error response describing why the operation failed.", + schema: { + $ref: "#/definitions/CloudError", + }, + }, + }, + "x-ms-examples": { + "Get a single private link association.": { + $ref: "./examples/GetPrivateLinkAssociation.json", + }, + }, + }, + delete: { + tags: ["PrivateLinkAssociation"], + operationId: "PrivateLinkAssociation_Delete", + description: "Delete a PrivateLinkAssociation", + parameters: [ + { + $ref: "#/parameters/ApiVersionParameter", + }, + { + $ref: "#/parameters/GroupIdParameter", + }, + { + $ref: "#/parameters/PrivateLinkAssociationIdParameter", + }, + ], + responses: { + "200": { + description: "OK", + }, + "204": { + description: "", + }, + default: { + description: "Error response describing why the operation failed.", + schema: { + $ref: "#/definitions/CloudError", }, }, }, + "x-ms-examples": { + "Delete a private link association.": { + $ref: "./examples/DeletePrivateLinkAssociation.json", + }, + }, }, }, - definitions: { - Bread: { - type: "object", - properties: { - name: { - description: "bread name", - type: "string", + "/providers/Microsoft.Management/managementGroups/{groupId}/providers/Microsoft.Authorization/privateLinkAssociations": { + get: { + tags: ["PrivateLinkAssociation"], + operationId: "PrivateLinkAssociation_List", + description: "Get a private link association for a management group scope", + parameters: [ + { + $ref: "#/parameters/ApiVersionParameter", + }, + { + $ref: "#/parameters/GroupIdParameter", + }, + ], + responses: { + "200": { + description: "Ok. The request has succeeded", + schema: { + $ref: "#/definitions/PrivateLinkAssociationGetResult", + }, + }, + default: { + description: "Error response describing why the operation failed.", + schema: { + $ref: "#/definitions/CloudError", + }, + }, + }, + "x-ms-examples": { + "Get a private link association for a MG scope.": { + $ref: "./examples/ListPrivateLinkAssociation.json", }, }, }, }, - } - - return nonResolvingLinter.run(oasDoc).then((results) => { - expect(results.length).toBe(1) - expect(results[0].message).toBe( - "Resource definition 'Bread' must reference the common types resource definition for ProxyResource or TrackedResource." - ) - }) -}) - -test(`${RULE} should find no errors`, async () => { - const oasDoc = { - swagger: "2.0", - paths: { - "/providers/Microsoft.Bakery/breads/{breadName}": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Authorization/resourceManagementPrivateLinks/{rmplName}": + { + put: { + tags: ["ResourceManagementPrivateLink"], + operationId: "ResourceManagementPrivateLink_Put", + description: "Create a resource management group private link.", + parameters: [ + { + $ref: "#/parameters/SubscriptionIdParameter", + }, + { + name: "resourceGroupName", + in: "path", + required: true, + type: "string", + description: "The name of the resource group. The name is case insensitive.", + minLength: 1, + maxLength: 90, + }, + { + $ref: "#/parameters/ApiVersionParameter", + }, + { + $ref: "#/parameters/ResourceManagementPrivateLinkParameter", + }, + { + name: "parameters", + in: "body", + required: true, + schema: { + $ref: "#/definitions/ResourceManagementPrivateLinkLocation", + }, + description: "The region to create the Resource Management private link.", + }, + ], + responses: { + "200": { + description: "OK. Returns information about the Resource Management Private Link.", + schema: { + $ref: "#/definitions/ResourceManagementPrivateLink", + }, + }, + "201": { + description: "Created. Returns information about the Resource Management Private Link.", + schema: { + $ref: "#/definitions/ResourceManagementPrivateLink", + }, + }, + default: { + description: "Error response describing why the operation failed.", + schema: { + $ref: "#/definitions/CloudError", + }, + }, + }, + "x-ms-examples": { + "Create Resource Management Private Link.": { + $ref: "./examples/PutResourceManagementPrivateLink.json", + }, + }, + }, get: { + tags: ["ResourceManagementPrivateLink"], + operationId: "ResourceManagementPrivateLink_Get", + description: "Get a resource management private link(resource-level).", + parameters: [ + { + $ref: "#/parameters/SubscriptionIdParameter", + }, + { + name: "resourceGroupName", + in: "path", + required: true, + type: "string", + description: "The name of the resource group. The name is case insensitive.", + minLength: 1, + maxLength: 90, + }, + { + $ref: "#/parameters/ApiVersionParameter", + }, + { + $ref: "#/parameters/ResourceManagementPrivateLinkParameter", + }, + ], responses: { - 200: { - description: "a response", + "200": { + description: "Ok. Returns information about the resource management private link.", schema: { - $ref: "#/definitions/Bread", + $ref: "#/definitions/ResourceManagementPrivateLink", }, }, + default: { + description: "Error response describing why the operation failed.", + schema: { + $ref: "#/definitions/CloudError", + }, + }, + }, + "x-ms-examples": { + "Get a Resource Management Private Link(resource-level).": { + $ref: "./examples/GetResourceManagementPrivateLink.json", + }, }, }, - put: { + patch: { + tags: ["ResourceManagementPrivateLink"], + operationId: "ResourceManagementPrivateLink_Update", + description: "Update a resource management private link.", + parameters: [ + { + $ref: "#/parameters/SubscriptionIdParameter", + }, + { + name: "resourceGroupName", + in: "path", + required: true, + type: "string", + description: "The name of the resource group. The name is case insensitive.", + minLength: 1, + maxLength: 90, + }, + { + $ref: "#/parameters/ApiVersionParameter", + }, + { + $ref: "#/parameters/ResourceManagementPrivateLinkParameter", + }, + { + name: "parameters", + in: "body", + required: true, + schema: { + $ref: "#/definitions/ResourceManagementPrivateLinkPatch", + }, + description: "Patch parameters for Resource Management private link.", + }, + ], + responses: { + "200": { + description: "OK. Returns information about the Resource Management Private Link.", + schema: { + $ref: "#/definitions/ResourceManagementPrivateLink", + }, + }, + default: { + description: "Error response describing why the operation failed.", + schema: { + $ref: "#/definitions/CloudError", + }, + }, + }, + "x-ms-examples": { + "Update Resource Management Private Link.": { + $ref: "./examples/PatchResourceManagementPrivateLink.json", + }, + }, + }, + delete: { + tags: ["ResourceManagementPrivateLink"], + operationId: "ResourceManagementPrivateLink_Delete", + description: "Delete a resource management private link.", + parameters: [ + { + $ref: "#/parameters/SubscriptionIdParameter", + }, + { + name: "resourceGroupName", + in: "path", + required: true, + type: "string", + description: "The name of the resource group. The name is case insensitive.", + minLength: 1, + maxLength: 90, + }, + { + $ref: "#/parameters/ApiVersionParameter", + }, + { + $ref: "#/parameters/ResourceManagementPrivateLinkParameter", + }, + ], responses: { - 200: { - description: "a response", + "200": { + description: "OK", + }, + "204": { + description: "", + }, + default: { + description: "Error response describing why the operation failed.", schema: { - $ref: "#/definitions/Bread", + $ref: "#/definitions/CloudError", }, }, }, + "x-ms-examples": { + "Delete a Resource Management Private Link.": { + $ref: "./examples/DeleteResourceManagementPrivateLink.json", + }, + }, + }, + }, + "/subscriptions/{subscriptionId}/providers/Microsoft.Authorization/resourceManagementPrivateLinks": { + get: { + tags: ["ResourceManagementPrivateLink"], + operationId: "ResourceManagementPrivateLink_List", + description: "Get all the resource management private links in a subscription.", + parameters: [ + { + $ref: "#/parameters/SubscriptionIdParameter", + }, + { + $ref: "#/parameters/ApiVersionParameter", + }, + ], + responses: { + "200": { + description: "Ok - Returns an array of private links.", + schema: { + $ref: "#/definitions/ResourceManagementPrivateLinkListResult", + }, + }, + default: { + description: "Error response describing why the operation failed.", + schema: { + $ref: "#/definitions/CloudError", + }, + }, + }, + "x-ms-examples": { + "Delete a Resource Management Private Link.": { + $ref: "./examples/ListSubscriptionResourceManagementPrivateLink.json", + }, }, }, }, - "/providers/Microsoft.Bakery/cookies/{cookieName}": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Authorization/resourceManagementPrivateLinks": { get: { + tags: ["ResourceManagementPrivateLink"], + operationId: "ResourceManagementPrivateLink_ListByResourceGroup", + description: "Get all the resource management private links in a resource group.", + parameters: [ + { + $ref: "#/parameters/SubscriptionIdParameter", + }, + { + name: "resourceGroupName", + in: "path", + required: true, + type: "string", + description: "The name of the resource group. The name is case insensitive.", + minLength: 1, + maxLength: 90, + }, + { + $ref: "#/parameters/ApiVersionParameter", + }, + ], responses: { - 200: { - description: "a response", + "200": { + description: "Ok - Returns an array of private links.", schema: { - $ref: "#/definitions/Cookie", + $ref: "#/definitions/ResourceManagementPrivateLinkListResult", }, }, + default: { + description: "Error response describing why the operation failed.", + schema: { + $ref: "#/definitions/CloudError", + }, + }, + }, + "x-ms-examples": { + "Delete a Resource Management Private Link.": { + $ref: "./examples/ListResourceGroupResourceManagementPrivateLink.json", + }, }, }, - put: { + }, + "/providers/Microsoft.Authorization/enablePrivateLinkNetworkAccess": { + post: { + tags: ["EnablePrivateLinkNetworkAccess"], + operationId: "EnablePrivateLinkNetworkAccess_Post", + description: "Enable private link network access for global administrator", + parameters: [ + { + $ref: "#/parameters/ApiVersionParameter", + }, + { + name: "parameters", + in: "body", + required: true, + schema: { + $ref: "#/definitions/EnablePrivateLinkNetworkAccessObject", + }, + description: "Parameters supplied to enable private link network access.", + }, + ], + responses: { + "200": { + description: "Post Succeed.", + }, + "202": { + description: "Accepted - Returns an Azure async operation header with HttpStatusCode 202.", + headers: { + "Azure-AsyncOperation": { + type: "string", + }, + Location: { + type: "string", + }, + }, + }, + default: { + description: "Error response describing why the operation failed.", + schema: { + $ref: "#/definitions/CloudError", + }, + }, + }, + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation", + }, + "x-ms-examples": { + "Enable a private link network access.": { + $ref: "./examples/PostEnablePrivateLinkNetworkAccess.json", + }, + }, + }, + }, + "/providers/Microsoft.Authorization/operations": { + get: { + tags: ["Operations"], + operationId: "AuthorizationOperations_List", + description: "Lists all of the available Microsoft.Authorization REST API operations.", + parameters: [ + { + $ref: "../../../../../common-types/resource-management/v2/types.json#/parameters/ApiVersionParameter", + }, + ], responses: { - 200: { - description: "a response", + "200": { + description: "OK. The request has succeeded.", schema: { - $ref: "#/definitions/Cookie", + $ref: "../../../../../common-types/resource-management/v2/types.json#/definitions/OperationListResult", }, }, + default: { + description: "Error response describing why the operation failed.", + schema: { + $ref: "../../../../../common-types/resource-management/v2/types.json#/definitions/ErrorResponse", + }, + }, + }, + "x-ms-pageable": { + nextLinkName: "nextLink", + }, + "x-ms-examples": { + "List provider operations": { + $ref: "./examples/ListProviderOperations.json", + }, }, }, }, - definitions: { - Bread: { - type: "object", + }, + definitions: { + PrivateLinkAssociationObject: { + type: "object", + properties: { properties: { - name: { - description: "bread name", - type: "string", + $ref: "#/definitions/PrivateLinkAssociationProperties", + description: "The properties of the PrivateLinkAssociation.", + }, + }, + }, + EnablePrivateLinkNetworkAccessObject: { + type: "object", + properties: { + scope: { + type: "string", + description: "The scope of private link associations where network access is updated.", + }, + }, + }, + PrivateLinkAssociationProperties: { + type: "object", + properties: { + privateLink: { + type: "string", + description: "The rmpl Resource ID.", + }, + publicNetworkAccess: { + type: "string", + enum: ["Enabled", "Disabled"], + "x-ms-enum": { + name: "publicNetworkAccessOptions", + modelAsString: true, }, - allOf: [ - { - $ref: "../../../../../common-types/resource-management/v1/types.json#/definitions/ProxyResource", - }, - ], }, }, }, - Cookie: { + PrivateLinkAssociationGetResult: { + description: "Result of the request to get PLA for a MG scope. ", type: "object", properties: { + value: { + type: "array", + items: { + $ref: "#/definitions/PrivateLinkAssociation", + }, + description: "private link association information.", + }, + }, + }, + PrivateLinkAssociationPropertiesExpanded: { + type: "object", + properties: { + privateLink: { + type: "string", + description: "The rmpl Resource ID.", + }, + publicNetworkAccess: { + type: "string", + enum: ["Enabled", "Disabled"], + "x-ms-enum": { + name: "publicNetworkAccessOptions", + modelAsString: true, + }, + }, + tenantID: { + type: "string", + description: "The TenantID.", + }, + scope: { + type: "string", + description: "The scope of the private link association.", + }, + }, + description: "Private Link Association Properties.", + }, + PrivateLinkAssociation: { + type: "object", + allOf: [ + { + $ref: "../../../../../common-types/resource-management/v2/types.json#/definitions/ProxyResource", + }, + ], + properties: { + properties: { + $ref: "#/definitions/PrivateLinkAssociationPropertiesExpanded", + description: "The private link association properties.", + }, + id: { + readOnly: true, + type: "string", + description: "The plaResourceID.", + }, + type: { + readOnly: true, + type: "string", + description: "The operation type.", + }, name: { - description: "cookie name", + readOnly: true, type: "string", + description: "The pla name.", }, - allOf: [ - { - $ref: "../../../../../common-types/resource-management/v1/types.json#/definitions/TrackedResource", + }, + }, + ResourceManagementPrivateLink: { + type: "object", + allOf: [ + { + $ref: "../../../../../common-types/resource-management/v2/types.json#/definitions/ProxyResource", + }, + ], + properties: { + properties: { + $ref: "#/definitions/ResourceManagementPrivateLinkEndpointConnections", + }, + id: { + readOnly: true, + type: "string", + description: "The rmplResourceID.", + }, + name: { + readOnly: true, + type: "string", + description: "The rmpl Name.", + }, + type: { + readOnly: true, + type: "string", + description: "The operation type.", + }, + location: { + type: "string", + description: "the region of the rmpl", + }, + tags: { + description: "The resource tags.", + type: "object", + additionalProperties: { + type: "string", }, - ], + }, }, + "x-ms-azure-resource": true, }, - } - - return nonResolvingLinter.run(oasDoc).then((results) => { - expect(results.length).toBe(0) - }) -}) + ResourceManagementPrivateLinkLocation: { + type: "object", + properties: { + location: { + type: "string", + description: "the region to create private link association.", + }, + }, + }, + ResourceManagementPrivateLinkPatch: { + type: "object", + properties: { + tags: { + description: "Resource tags.", + type: "object", + additionalProperties: { + type: "string", + "x-nullable": true, + }, + }, + }, + }, + ResourceManagementPrivateLinkEndpointConnections: { + type: "object", + properties: { + privateEndpointConnections: { + type: "array", + items: { + type: "string", + }, + description: "The private endpoint connections.", + }, + }, + }, + ResourceManagementPrivateLinkListResult: { + type: "object", + properties: { + value: { + type: "array", + items: { + $ref: "#/definitions/ResourceManagementPrivateLink", + }, + description: "An array of resource management private links.", + }, + }, + }, + CloudError: { + "x-ms-external": true, + type: "object", + properties: { + error: { + $ref: "../../../../../common-types/resource-management/v1/types.json#/definitions/ErrorResponse", + }, + }, + description: "An error response for a resource management request.", + }, + }, + parameters: { + ApiVersionParameter: { + name: "api-version", + in: "query", + required: true, + type: "string", + description: "The API version to use for this operation.", + "x-ms-parameter-location": "client", + }, + GroupIdParameter: { + name: "groupId", + in: "path", + required: true, + type: "string", + description: "The management group ID.", + "x-ms-parameter-location": "method", + minLength: 1, + maxLength: 90, + }, + SubscriptionIdParameter: { + name: "subscriptionId", + in: "path", + required: true, + type: "string", + description: "The ID of the target subscription.", + "x-ms-parameter-location": "method", + }, + PrivateLinkAssociationIdParameter: { + name: "plaId", + in: "path", + required: true, + type: "string", + description: "The ID of the PLA", + "x-ms-parameter-location": "method", + }, + ResourceManagementPrivateLinkParameter: { + name: "rmplName", + in: "path", + required: true, + type: "string", + description: "The name of the resource management private link.", + "x-ms-parameter-location": "method", + }, + }, +}