diff --git a/docs/get-collection-only-has-value-nextlink.md b/docs/get-collection-only-has-value-nextlink.md index 5cb08bd9c..36ec376ed 100644 --- a/docs/get-collection-only-has-value-nextlink.md +++ b/docs/get-collection-only-has-value-nextlink.md @@ -1,4 +1,4 @@ -# GetCollectionOnlyHasValueAndNextLink +# GetCollectionResponseSchema ## Category @@ -18,8 +18,10 @@ List GET endpoints (collection GET) must only have `value` and `nextLink` in `pr ## Why the rule is important -This rule is important to retain consistency between ARM APIs. Furthermore, not adhering to this rule will cause issues with Azure Resource Graph (ARG) integration. +This rule is important to retain consistency between ARM APIs. Furthermore, not adhering to this rule will cause issues +with Azure Resource Graph (ARG) integration. ## How to fix the violation -Under `properties` in the schema for GET endpoints, ensure the fields `value` and `nextLink` are present, and no other fields are present. +Under `properties` in the schema for GET endpoints, ensure the fields `value` and `nextLink` are present, and no other +fields are present. diff --git a/docs/rules.md b/docs/rules.md index d12d646d2..1529e2edb 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -330,7 +330,7 @@ Instead, consider defining a `body` parameter with `type: string, format: binary Please refer to [formdata.md](./formdata.md) for details. -### GetCollectionOnlyHasValueAndNextLink +### GetCollectionResponseSchema List GET endpoints (collection GET) must only have `value` and `nextLink` in `properties`. diff --git a/packages/rulesets/generated/spectral/az-arm.js b/packages/rulesets/generated/spectral/az-arm.js index e11a07721..3159882af 100644 --- a/packages/rulesets/generated/spectral/az-arm.js +++ b/packages/rulesets/generated/spectral/az-arm.js @@ -2682,7 +2682,7 @@ const ruleset = { function: falsy, }, }, - GetCollectionOnlyHasValueAndNextLink: { + GetCollectionResponseSchema: { description: "Get endpoints for collections of resources must only have the `value` and `nextLink` properties in their model.", message: "{{description}}", severity: "error", diff --git a/packages/rulesets/src/spectral/az-arm.ts b/packages/rulesets/src/spectral/az-arm.ts index b74911bab..bd62c1574 100644 --- a/packages/rulesets/src/spectral/az-arm.ts +++ b/packages/rulesets/src/spectral/az-arm.ts @@ -8,7 +8,7 @@ import collectionObjectPropertiesNaming from "./functions/collection-object-prop import { consistentPatchProperties } from "./functions/consistent-patch-properties" import { DeleteResponseCodes } from "./functions/delete-response-codes" import { longRunningResponseStatusCodeArm } from "./functions/Extensions/long-running-response-status-code" -import { getCollectionOnlyHasValueAndNextLink } from "./functions/get-collection-only-has-value-nextlink" +import { getCollectionResponseSchema } from "./functions/get-collection-response-schema" import hasApiVersionParameter from "./functions/has-api-version-parameter" import hasheader from "./functions/has-header" import httpsSupportedScheme from "./functions/https-supported-scheme" @@ -290,15 +290,16 @@ const ruleset: any = { }, }, // RPC Codes: RPC-Get-V1-09, RPC-Arg-V1-01, RPC-Get-V1-06 - GetCollectionOnlyHasValueAndNextLink: { + GetCollectionResponseSchema: { description: "Get endpoints for collections of resources must only have the `value` and `nextLink` properties in their model.", message: "{{description}}", severity: "error", resolved: true, formats: [oas2], - given: "$[paths,'x-ms-paths'][?(!@property.endsWith('}') && !@property.endsWith('operations'))][get].responses.200.schema.properties", + given: + "$[paths,'x-ms-paths'][?(!@property.endsWith('}') && @property.endsWith('s') && !@property.endsWith('operations'))][get].responses.200.schema.properties", then: { - function: getCollectionOnlyHasValueAndNextLink, + function: getCollectionResponseSchema, }, }, diff --git a/packages/rulesets/src/spectral/functions/get-collection-only-has-value-nextlink.ts b/packages/rulesets/src/spectral/functions/get-collection-only-has-value-nextlink.ts deleted file mode 100644 index 52311a442..000000000 --- a/packages/rulesets/src/spectral/functions/get-collection-only-has-value-nextlink.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Verifies that collection get schemas have only the `value` and `nextLink` properties in their models. - -export const getCollectionOnlyHasValueAndNextLink = (properties: any, _opts: any, ctx: any) => { - if (!properties || typeof properties !== "object") { - return [] - } - const keys = Object.keys(properties) - - if (keys.length != 2 || !keys.includes("value") || !keys.includes("nextLink")) { - return [ - { - message: "Get endpoints for collections of resources must only have the `value` and `nextLink` properties in their model.", - }, - ] - } - return [] -} diff --git a/packages/rulesets/src/spectral/functions/get-collection-response-schema.ts b/packages/rulesets/src/spectral/functions/get-collection-response-schema.ts new file mode 100644 index 000000000..29db744c6 --- /dev/null +++ b/packages/rulesets/src/spectral/functions/get-collection-response-schema.ts @@ -0,0 +1,23 @@ +// Verifies that collection get schemas have only the `value` and `nextLink` properties in their models. + +const ALLOWED_KEYS = ["value", "nextLink"] +const ERROR_MESSAGE = "Get endpoints for collections of resources must only have the `value` and `nextLink` properties in their model." + +// TODO: might need to use something like getCollectionApiInfo() in arm-helper.ts +// TODO: can't call it this. there already is a rule fo this GetCollectionResponseSchema.ts + +export const getCollectionResponseSchema = (properties: any, _opts: any, ctx: any) => { + if (!properties || typeof properties !== "object") { + return [] + } + const keys = Object.keys(properties) + + if (keys.length > 2 || keys.some((key) => !ALLOWED_KEYS.includes(key))) { + return [ + { + message: ERROR_MESSAGE, + }, + ] + } + return [] +} diff --git a/packages/rulesets/src/spectral/test/get-collection-only-has-value-nextlink.test.ts b/packages/rulesets/src/spectral/test/get-collection-only-has-value-nextlink.test.ts index 75af0fe5a..cb6b3b535 100644 --- a/packages/rulesets/src/spectral/test/get-collection-only-has-value-nextlink.test.ts +++ b/packages/rulesets/src/spectral/test/get-collection-only-has-value-nextlink.test.ts @@ -4,11 +4,11 @@ import linterForRule from "./utils" let linter: Spectral beforeAll(async () => { - linter = await linterForRule("GetCollectionOnlyHasValueAndNextLink") + linter = await linterForRule("GetCollectionResponseSchema") return linter }) -test("GetCollectionOnlyHasValueAndNextLink should find no errors when get collection schema has only value and nextLink properties", () => { +test("GetCollectionResponseSchema should find no errors when get collection schema has only value and nextLink properties", () => { const myOpenApiDocument = { swagger: "2.0", paths: { @@ -66,7 +66,7 @@ test("GetCollectionOnlyHasValueAndNextLink should find no errors when get collec }) }) -test("GetCollectionOnlyHasValueAndNextLink should find errors when get collection schema has properties other than value and nextLink", () => { +test("GetCollectionResponseSchema should find errors when get collection schema has properties other than value and nextLink", () => { const myOpenApiDocument = { swagger: "2.0", paths: { @@ -131,7 +131,7 @@ test("GetCollectionOnlyHasValueAndNextLink should find errors when get collectio }) }) -test("GetCollectionOnlyHasValueAndNextLink should find errors when nextLink is missing", () => { +test("GetCollectionResponseSchema should find errors when nextLink is missing", () => { const myOpenApiDocument = { swagger: "2.0", paths: { @@ -188,7 +188,7 @@ test("GetCollectionOnlyHasValueAndNextLink should find errors when nextLink is m }) }) -test("GetCollectionOnlyHasValueAndNextLink should find errors when value is missing", () => { +test("GetCollectionResponseSchema should find errors when value is missing", () => { const myOpenApiDocument = { swagger: "2.0", paths: {