diff --git a/tools/src/merger/OpenApiVersionExtractor.ts b/tools/src/merger/OpenApiVersionExtractor.ts index c467cbd2d..560a962bc 100644 --- a/tools/src/merger/OpenApiVersionExtractor.ts +++ b/tools/src/merger/OpenApiVersionExtractor.ts @@ -43,7 +43,8 @@ export default class OpenApiVersionExtractor { return this } - // Remove any refs that are x-version-added/removed incompatible with the target server version. + // Remove any refs and objects that reference them that are x-version-added/removed + // incompatible with the target server version. #extract() : void { this._logger.info(`Extracting version ${this._target_version} ...`) @@ -77,6 +78,10 @@ export default class OpenApiVersionExtractor { }) this._spec.paths = _.omitBy(this._spec.paths, isEmpty) + + this.#remove_unused_bodies() + this.#remove_unused_parameters() + this.#remove_unused_responses() } #exclude_per_semver(obj: any): boolean { @@ -99,4 +104,61 @@ export default class OpenApiVersionExtractor { if (this._target_version === undefined) return [] return delete_matching_keys(obj, this.#exclude_per_semver.bind(this)) } + + #remove_unused_bodies(): void { + if (this._spec === undefined) return + + var used_bodies: string[] = [] + Object.entries(this._spec.paths as Document).forEach(([_path, path_item]) => { + Object.entries(path_item as Document).forEach(([_method, method_item]) => { + if (method_item.requestBody?.$ref !== undefined) { + used_bodies = _.concat(used_bodies, method_item.requestBody.$ref) + } + }) + }) + + this._spec.components.requestBodies = _.pickBy(this._spec.components.requestBodies, (_value, key) => + _.includes(used_bodies, `#/components/requestBodies/${key}`) + ) + } + + + #remove_unused_responses(): void { + if (this._spec === undefined) return + + var used_responses: string[] = [] + Object.entries(this._spec.paths as Document).forEach(([_path, path_item]) => { + Object.entries(path_item as Document).forEach(([_method, method_item]) => { + Object.entries(method_item.responses as Document).forEach(([_response_code, response]) => { + if (response.$ref !== undefined) { + used_responses = _.concat(used_responses, response.$ref) + } + }) + }) + }) + + this._spec.components.responses = _.pickBy(this._spec.components.responses, (_value, key) => + _.includes(used_responses, `#/components/responses/${key}`) + ) + } + + + #remove_unused_parameters(): void { + if (this._spec === undefined) return + + var used_parameters: string[] = [] + Object.entries(this._spec.paths as Document).forEach(([_path, path_item]) => { + Object.entries(path_item as Document).forEach(([_method, method_item]) => { + Object.entries(method_item.parameters as Document).forEach(([_response_code, parameter]) => { + if (parameter.$ref !== undefined) { + used_parameters = _.concat(used_parameters, parameter.$ref) + } + }) + }) + }) + + this._spec.components.parameters = _.pickBy(this._spec.components.parameters, (_value, key) => + _.includes(used_parameters, `#/components/parameters/${key}`) + ) + } } diff --git a/tools/tests/merger/OpenApiVersionExtractor.test.ts b/tools/tests/merger/OpenApiVersionExtractor.test.ts index d0b8aa6a7..2a5bd28a9 100644 --- a/tools/tests/merger/OpenApiVersionExtractor.test.ts +++ b/tools/tests/merger/OpenApiVersionExtractor.test.ts @@ -23,7 +23,7 @@ describe('extract() from a merged API spec', () => { const spec = extractor.extract() expect(_.keys(spec.paths['/index']?.get?.responses)).toEqual([ - '200', '201', '404', '500', 'added-2.0', 'removed-2.0', 'added-1.3-removed-2.0', 'added-2.1' + '200', '201', '404', '500', '503', 'added-2.0', 'removed-2.0', 'added-1.3-removed-2.0', 'added-2.1' ]) }) @@ -76,7 +76,7 @@ describe('extract() from a merged API spec', () => { test('has matching responses', () => { const spec = extractor.extract() expect(_.keys(spec.paths['/index']?.get?.responses)).toEqual([ - '200', '201', '404', '500', 'removed-2.0', 'added-1.3-removed-2.0' + '200', '201', '404', '500', '503', 'removed-2.0', 'added-1.3-removed-2.0' ]) }) @@ -86,7 +86,7 @@ describe('extract() from a merged API spec', () => { test('has matching responses', () => { const spec = extractor.extract() expect(_.keys(spec.paths['/index']?.get?.responses)).toEqual([ - '200', '201', '404', '500', 'added-2.0' + '200', '201', '404', '500', '503', 'added-2.0' ]) }) }) @@ -97,7 +97,7 @@ describe('extract() from a merged API spec', () => { test('has matching responses', () => { const spec = extractor.extract() expect(_.keys(spec.paths['/index']?.get?.responses)).toEqual([ - '200', '201', '404', '500', 'added-2.0', 'added-2.1' + '200', '201', '404', '500', '503', 'added-2.0', 'added-2.1' ]) }) }) diff --git a/tools/tests/merger/fixtures/extractor/expected_1.3.yaml b/tools/tests/merger/fixtures/extractor/expected_1.3.yaml index 3958db67b..42791f2ee 100644 --- a/tools/tests/merger/fixtures/extractor/expected_1.3.yaml +++ b/tools/tests/merger/fixtures/extractor/expected_1.3.yaml @@ -16,18 +16,6 @@ paths: responses: '200': $ref: '#/components/responses/nodes.info@200' - post: - operationId: nodes.info.1 - x-operation-group: nodes.info - x-version-added: '1.0' - description: Returns information about nodes in the cluster. - parameters: - - $ref: '#/components/parameters/nodes.info::path.id' - requestBody: - $ref: '#/components/requestBodies/nodes.info' - responses: - '200': - $ref: '#/components/responses/nodes.info@200' /index: get: operationId: get.0 @@ -40,6 +28,8 @@ paths: $ref: '#/components/responses/info@404' '500': $ref: '#/components/responses/info@500' + '503': + $ref: '#/components/responses/info@503' removed-2.0: $ref: '#/components/responses/info@removed-2.0' x-version-removed: '2.0' @@ -62,16 +52,7 @@ components: required: true schema: type: string - requestBodies: - nodes.info: - content: - application/json: - schema: - type: object - properties: - _all: - type: boolean - description: Nodes options. + requestBodies: {} responses: info@200: description: '' @@ -128,8 +109,6 @@ components: description: Added in 1.3, removed in 2.0 via attribute in response body. x-version-added: '1.3' x-version-removed: '2.0' - info@added-2.0: - description: Added in 2.0 via attribute next to ref. info@removed-2.0: description: Removed in 2.0 via attribute next to ref. nodes.info@200: diff --git a/tools/tests/merger/fixtures/extractor/expected_2.0.yaml b/tools/tests/merger/fixtures/extractor/expected_2.0.yaml index 883e167b0..6cb54f13b 100644 --- a/tools/tests/merger/fixtures/extractor/expected_2.0.yaml +++ b/tools/tests/merger/fixtures/extractor/expected_2.0.yaml @@ -19,15 +19,18 @@ paths: post: operationId: nodes.info.1 x-operation-group: nodes.info - x-version-added: '1.0' + x-version-added: '2.0' description: Returns information about nodes in the cluster. parameters: - $ref: '#/components/parameters/nodes.info::path.id' + - $ref: '#/components/parameters/nodes.info::query.flag' requestBody: $ref: '#/components/requestBodies/nodes.info' responses: '200': $ref: '#/components/responses/nodes.info@200' + '201': + $ref: '#/components/responses/nodes.info@201' /index: get: operationId: get.0 @@ -40,6 +43,8 @@ paths: $ref: '#/components/responses/info@404' '500': $ref: '#/components/responses/info@500' + '503': + $ref: '#/components/responses/info@503' added-2.0: $ref: '#/components/responses/info@added-2.0' x-version-added: '2.0' @@ -67,6 +72,14 @@ components: required: true schema: type: string + nodes.info::query.flag: + in: query + name: flag + description: Flag. + required: false + schema: + type: boolean + default: false requestBodies: nodes.info: content: @@ -146,4 +159,10 @@ components: application/json: schema: type: object + nodes.info@201: + description: All nodes. + content: + application/json: + schema: + type: object schemas: {} diff --git a/tools/tests/merger/fixtures/merger/expected.yaml b/tools/tests/merger/fixtures/merger/expected.yaml index 3b547b720..ef0560ad2 100644 --- a/tools/tests/merger/fixtures/merger/expected.yaml +++ b/tools/tests/merger/fixtures/merger/expected.yaml @@ -90,7 +90,9 @@ components: type: boolean requestBodies: adopt: {} - indices.create: {} + indices.create: + name: + type: string responses: adopt@200: description: '' diff --git a/tools/tests/merger/fixtures/spec/namespaces/indices.yaml b/tools/tests/merger/fixtures/spec/namespaces/indices.yaml index 0dafa08e7..d5f1fcb9c 100644 --- a/tools/tests/merger/fixtures/spec/namespaces/indices.yaml +++ b/tools/tests/merger/fixtures/spec/namespaces/indices.yaml @@ -19,7 +19,9 @@ paths: x-version-added: '2.0' components: requestBodies: - indices.create: {} + indices.create: + name: + type: string parameters: indices.create::path.index: name: index diff --git a/tools/tests/tester/MergedOpenApiSpec.test.ts b/tools/tests/tester/MergedOpenApiSpec.test.ts index 80211c140..e8c78cc65 100644 --- a/tools/tests/tester/MergedOpenApiSpec.test.ts +++ b/tools/tests/tester/MergedOpenApiSpec.test.ts @@ -29,7 +29,7 @@ describe('merged API spec', () => { test('has all responses', () => { expect(_.keys(spec.spec().paths['/index']?.get?.responses)).toEqual([ - '200', '201', '404', '500', 'added-2.0', 'removed-2.0', 'added-1.3-removed-2.0', 'added-2.1' + '200', '201', '404', '500','503', 'added-2.0', 'removed-2.0', 'added-1.3-removed-2.0', 'added-2.1' ]) }) @@ -68,7 +68,7 @@ describe('merged API spec', () => { test('has matching responses', () => { expect(_.keys(spec.spec().paths['/index']?.get?.responses)).toEqual([ - '200', '201', '404', '500', 'removed-2.0', 'added-1.3-removed-2.0' + '200', '201', '404', '500', '503', 'removed-2.0', 'added-1.3-removed-2.0' ]) }) }) @@ -78,7 +78,7 @@ describe('merged API spec', () => { test('has matching responses', () => { expect(_.keys(spec.spec().paths['/index']?.get?.responses)).toEqual([ - '200', '201', '404', '500', 'added-2.0' + '200', '201', '404', '500', '503', 'added-2.0' ]) }) }) @@ -88,7 +88,7 @@ describe('merged API spec', () => { test('has matching responses', () => { expect(_.keys(spec.spec().paths['/index']?.get?.responses)).toEqual([ - '200', '201', '404', '500', 'added-2.0', 'added-2.1' + '200', '201', '404', '500', '503', 'added-2.0', 'added-2.1' ]) }) }) diff --git a/tools/tests/tester/fixtures/specs/complete/namespaces/index.yaml b/tools/tests/tester/fixtures/specs/complete/namespaces/index.yaml index 141ca5ac5..e578781f1 100644 --- a/tools/tests/tester/fixtures/specs/complete/namespaces/index.yaml +++ b/tools/tests/tester/fixtures/specs/complete/namespaces/index.yaml @@ -26,6 +26,8 @@ paths: $ref: '#/components/responses/info@added-2.1' '500': $ref: '#/components/responses/info@500' + '503': + $ref: '#/components/responses/info@503' components: responses: info@200: diff --git a/tools/tests/tester/fixtures/specs/complete/namespaces/nodes.yaml b/tools/tests/tester/fixtures/specs/complete/namespaces/nodes.yaml index 87abb9dbe..0fae3a8ca 100644 --- a/tools/tests/tester/fixtures/specs/complete/namespaces/nodes.yaml +++ b/tools/tests/tester/fixtures/specs/complete/namespaces/nodes.yaml @@ -24,13 +24,16 @@ paths: post: operationId: nodes.info.1 x-operation-group: nodes.info - x-version-added: '1.0' + x-version-added: '2.0' description: Returns information about nodes in the cluster. parameters: - $ref: '#/components/parameters/nodes.info::path.id' + - $ref: '#/components/parameters/nodes.info::query.flag' requestBody: $ref: '#/components/requestBodies/nodes.info' responses: + '201': + $ref: '#/components/responses/nodes.info@201' '200': $ref: '#/components/responses/nodes.info@200' components: @@ -52,6 +55,14 @@ components: required: true schema: type: string + nodes.info::query.flag: + in: query + name: flag + description: Flag. + required: false + schema: + type: boolean + default: false responses: nodes.info@200: description: All nodes. @@ -59,3 +70,9 @@ components: application/json: schema: type: object + nodes.info@201: + description: All nodes. + content: + application/json: + schema: + type: object