diff --git a/tools/cli/internal/openapi/filter/sunset.go b/tools/cli/internal/openapi/filter/sunset.go index 2f11c8f854..fcd0241c67 100644 --- a/tools/cli/internal/openapi/filter/sunset.go +++ b/tools/cli/internal/openapi/filter/sunset.go @@ -49,7 +49,12 @@ func (f *SunsetFilter) Apply() error { return nil } +// applyOnOperation removes the "sunset" extension if its value is set to "sunsetToBeDecided". +// The "sunset" extension can be located in two places. +// 1) Within the 20X response. +// 2) As part of the operation itself. func applyOnOperation(op *openapi3.Operation) { + // 1) Check the "sunset" extension in the response for key, response := range op.Responses.Map() { if !strings.HasPrefix(key, "20") { continue @@ -61,4 +66,9 @@ func applyOnOperation(op *openapi3.Operation) { }) } } + + // 2) Check the "sunset" extension as part of the operation + maps.DeleteFunc(op.Extensions, func(_ string, v any) bool { + return v == sunsetToBeDecided + }) } diff --git a/tools/cli/internal/openapi/filter/sunset_test.go b/tools/cli/internal/openapi/filter/sunset_test.go index 29c144161b..07615aa74f 100644 --- a/tools/cli/internal/openapi/filter/sunset_test.go +++ b/tools/cli/internal/openapi/filter/sunset_test.go @@ -21,318 +21,409 @@ import ( ) func TestSunsetFilter_Apply(t *testing.T) { - testCases := []struct { - name string - initSpec *openapi3.T - wantedSpec *openapi3.T - }{ - { - name: "Remove x-sunset when value is 9999-12-31", - initSpec: &openapi3.T{ - Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{ - Get: &openapi3.Operation{ - OperationID: "testOperationID", - Summary: "testSummary", - Responses: openapi3.NewResponses(openapi3.WithName("200", &openapi3.Response{ - Content: openapi3.Content{ - "application/vnd.atlas.2025-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2025-01-01", - }, - }, - "application/vnd.atlas.2024-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2024-01-01", - "x-sunset": "2024-12-31", - }, - }, - "application/vnd.atlas.2023-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2023-01-01", - "x-sunset": "9999-12-31", - }, + testCases := []testCase{removeSunsetFromOperation(), + ignoreNot20XResponse(), + doNotRemoveSunset(), + removeSunsetToDecideFromResponse204(), + removeSunsetToDecideFromResponse()} + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + f := &SunsetFilter{ + oas: tc.initSpec, + } + + require.NoError(t, f.Apply()) + require.Equal(t, tc.wantedSpec, f.oas) + }) + } +} + +func removeSunsetFromOperation() testCase { + return testCase{ + name: "Remove x-sunset when value is 9999-12-31 and extension is in the operation", + initSpec: &openapi3.T{ + Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{ + Get: &openapi3.Operation{ + OperationID: "testOperationID", + Summary: "testSummary", + Responses: openapi3.NewResponses(openapi3.WithName("200", &openapi3.Response{ + Content: openapi3.Content{ + "application/vnd.atlas.2025-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2025-01-01", }, }, - })), - }, - })), - }, - wantedSpec: &openapi3.T{ - Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{ - Get: &openapi3.Operation{ - OperationID: "testOperationID", - Summary: "testSummary", - Responses: openapi3.NewResponses(openapi3.WithName("200", &openapi3.Response{ - Content: openapi3.Content{ - "application/vnd.atlas.2025-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2025-01-01", - }, - }, - "application/vnd.atlas.2024-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2024-01-01", - "x-sunset": "2024-12-31", - }, - }, - "application/vnd.atlas.2023-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2023-01-01", - }, + "application/vnd.atlas.2024-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2024-01-01", + "x-sunset": "2024-12-31", }, }, - })), + "application/vnd.atlas.2023-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2023-01-01", + }, + }, + }, + })), + Extensions: map[string]any{ + "x-sunset": "9999-12-31", }, - })), - }, + }, + })), }, - { - name: "Remove x-sunset when value is 9999-12-31 for a 204", - initSpec: &openapi3.T{ - Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{ - Get: &openapi3.Operation{ - OperationID: "testOperationID", - Summary: "testSummary", - Responses: openapi3.NewResponses(openapi3.WithName("204", &openapi3.Response{ - Content: openapi3.Content{ - "application/vnd.atlas.2025-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2025-01-01", - }, - }, - "application/vnd.atlas.2024-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2024-01-01", - "x-sunset": "2024-12-31", - }, - }, - "application/vnd.atlas.2023-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2023-01-01", - "x-sunset": "9999-12-31", - }, + wantedSpec: &openapi3.T{ + Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{ + Get: &openapi3.Operation{ + OperationID: "testOperationID", + Summary: "testSummary", + Responses: openapi3.NewResponses(openapi3.WithName("200", &openapi3.Response{ + Content: openapi3.Content{ + "application/vnd.atlas.2025-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2025-01-01", }, }, - })), - }, - })), - }, - wantedSpec: &openapi3.T{ - Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{ - Get: &openapi3.Operation{ - OperationID: "testOperationID", - Summary: "testSummary", - Responses: openapi3.NewResponses(openapi3.WithName("204", &openapi3.Response{ - Content: openapi3.Content{ - "application/vnd.atlas.2025-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2025-01-01", - }, - }, - "application/vnd.atlas.2024-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2024-01-01", - "x-sunset": "2024-12-31", - }, - }, - "application/vnd.atlas.2023-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2023-01-01", - }, + "application/vnd.atlas.2024-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2024-01-01", + "x-sunset": "2024-12-31", }, }, - })), - }, - })), - }, + "application/vnd.atlas.2023-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2023-01-01", + }, + }, + }, + })), + Extensions: map[string]any{}, + }, + })), }, - { - name: "Keep x-sunset when value is different", - initSpec: &openapi3.T{ - Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{ - Get: &openapi3.Operation{ - OperationID: "testOperationID", - Summary: "testSummary", - Responses: openapi3.NewResponses(openapi3.WithName("200", &openapi3.Response{ - Content: openapi3.Content{ - "application/vnd.atlas.2025-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2025-01-01", - }, - }, - "application/vnd.atlas.2024-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2024-01-01", - "x-sunset": "2024-12-31", - }, + } +} +func ignoreNot20XResponse() testCase { + return testCase{ + name: "Ignore non-2xx responses", + initSpec: &openapi3.T{ + Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{ + Get: &openapi3.Operation{ + OperationID: "testOperationID", + Summary: "testSummary", + Responses: openapi3.NewResponses(openapi3.WithName("404", &openapi3.Response{ + Content: openapi3.Content{ + "application/vnd.atlas.2025-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2025-01-01", }, }, - })), - }, - })), - }, - wantedSpec: &openapi3.T{ - Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{ - Get: &openapi3.Operation{ - OperationID: "testOperationID", - Summary: "testSummary", - Responses: openapi3.NewResponses(openapi3.WithName("200", &openapi3.Response{ - Content: openapi3.Content{ - "application/vnd.atlas.2025-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2025-01-01", - }, - }, - "application/vnd.atlas.2024-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2024-01-01", - "x-sunset": "2024-12-31", - }, + "application/vnd.atlas.2024-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2024-01-01", + "x-sunset": "2024-12-31", }, }, - })), - }, - })), - }, + "application/vnd.atlas.2023-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2023-01-01", + "x-sunset": "9999-12-31", + }, + }, + }, + })), + }, + })), }, - { - name: "Ignore non-2xx responses", - initSpec: &openapi3.T{ - Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{ - Get: &openapi3.Operation{ - OperationID: "testOperationID", - Summary: "testSummary", - Responses: openapi3.NewResponses(openapi3.WithName("404", &openapi3.Response{ - Content: openapi3.Content{ - "application/vnd.atlas.2025-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2025-01-01", - }, - }, - "application/vnd.atlas.2024-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2024-01-01", - "x-sunset": "2024-12-31", - }, - }, - "application/vnd.atlas.2023-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2023-01-01", - "x-sunset": "9999-12-31", - }, + wantedSpec: &openapi3.T{ + Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{ + Get: &openapi3.Operation{ + OperationID: "testOperationID", + Summary: "testSummary", + Responses: openapi3.NewResponses(openapi3.WithName("404", &openapi3.Response{ + Content: openapi3.Content{ + "application/vnd.atlas.2025-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2025-01-01", }, }, - })), - }, - })), - }, - wantedSpec: &openapi3.T{ - Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{ - Get: &openapi3.Operation{ - OperationID: "testOperationID", - Summary: "testSummary", - Responses: openapi3.NewResponses(openapi3.WithName("404", &openapi3.Response{ - Content: openapi3.Content{ - "application/vnd.atlas.2025-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2025-01-01", - }, - }, - "application/vnd.atlas.2024-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2024-01-01", - "x-sunset": "2024-12-31", - }, - }, - "application/vnd.atlas.2023-01-01+json": { - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/PaginatedAppUserView", - }, - Extensions: map[string]any{ - "x-gen-version": "2023-01-01", - "x-sunset": "9999-12-31", - }, + "application/vnd.atlas.2024-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2024-01-01", + "x-sunset": "2024-12-31", }, }, - })), - }, - })), - }, + "application/vnd.atlas.2023-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2023-01-01", + "x-sunset": "9999-12-31", + }, + }, + }, + })), + }, + })), }, } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - f := &SunsetFilter{ - oas: tc.initSpec, - } - - require.NoError(t, f.Apply()) - require.Equal(t, tc.wantedSpec, f.oas) - }) +} +func doNotRemoveSunset() testCase { + return testCase{ + name: "Keep x-sunset when value is different", + initSpec: &openapi3.T{ + Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{ + Get: &openapi3.Operation{ + OperationID: "testOperationID", + Summary: "testSummary", + Responses: openapi3.NewResponses(openapi3.WithName("200", &openapi3.Response{ + Content: openapi3.Content{ + "application/vnd.atlas.2025-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2025-01-01", + }, + }, + "application/vnd.atlas.2024-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2024-01-01", + "x-sunset": "2024-12-31", + }, + }, + }, + })), + }, + })), + }, + wantedSpec: &openapi3.T{ + Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{ + Get: &openapi3.Operation{ + OperationID: "testOperationID", + Summary: "testSummary", + Responses: openapi3.NewResponses(openapi3.WithName("200", &openapi3.Response{ + Content: openapi3.Content{ + "application/vnd.atlas.2025-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2025-01-01", + }, + }, + "application/vnd.atlas.2024-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2024-01-01", + "x-sunset": "2024-12-31", + }, + }, + }, + })), + }, + })), + }, + } +} +func removeSunsetToDecideFromResponse204() testCase { + return testCase{ + name: "Remove x-sunset when value is 9999-12-31 for a 204", + initSpec: &openapi3.T{ + Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{ + Get: &openapi3.Operation{ + OperationID: "testOperationID", + Summary: "testSummary", + Responses: openapi3.NewResponses(openapi3.WithName("204", &openapi3.Response{ + Content: openapi3.Content{ + "application/vnd.atlas.2025-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2025-01-01", + }, + }, + "application/vnd.atlas.2024-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2024-01-01", + "x-sunset": "2024-12-31", + }, + }, + "application/vnd.atlas.2023-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2023-01-01", + "x-sunset": "9999-12-31", + }, + }, + }, + })), + }, + })), + }, + wantedSpec: &openapi3.T{ + Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{ + Get: &openapi3.Operation{ + OperationID: "testOperationID", + Summary: "testSummary", + Responses: openapi3.NewResponses(openapi3.WithName("204", &openapi3.Response{ + Content: openapi3.Content{ + "application/vnd.atlas.2025-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2025-01-01", + }, + }, + "application/vnd.atlas.2024-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2024-01-01", + "x-sunset": "2024-12-31", + }, + }, + "application/vnd.atlas.2023-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2023-01-01", + }, + }, + }, + })), + }, + })), + }, + } +} +func removeSunsetToDecideFromResponse() testCase { + return testCase{ + name: "Remove x-sunset when value is 9999-12-31", + initSpec: &openapi3.T{ + Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{ + Get: &openapi3.Operation{ + OperationID: "testOperationID", + Summary: "testSummary", + Responses: openapi3.NewResponses(openapi3.WithName("200", &openapi3.Response{ + Content: openapi3.Content{ + "application/vnd.atlas.2025-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2025-01-01", + }, + }, + "application/vnd.atlas.2024-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2024-01-01", + "x-sunset": "2024-12-31", + }, + }, + "application/vnd.atlas.2023-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2023-01-01", + "x-sunset": "9999-12-31", + }, + }, + }, + })), + }, + })), + }, + wantedSpec: &openapi3.T{ + Paths: openapi3.NewPaths(openapi3.WithPath("test", &openapi3.PathItem{ + Get: &openapi3.Operation{ + OperationID: "testOperationID", + Summary: "testSummary", + Responses: openapi3.NewResponses(openapi3.WithName("200", &openapi3.Response{ + Content: openapi3.Content{ + "application/vnd.atlas.2025-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2025-01-01", + }, + }, + "application/vnd.atlas.2024-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2024-01-01", + "x-sunset": "2024-12-31", + }, + }, + "application/vnd.atlas.2023-01-01+json": { + Schema: &openapi3.SchemaRef{ + Ref: "#/components/schemas/PaginatedAppUserView", + }, + Extensions: map[string]any{ + "x-gen-version": "2023-01-01", + }, + }, + }, + })), + }, + })), + }, } }