From ad8a0f78cb6b39fb5bec4ecb153edffa67ef76c5 Mon Sep 17 00:00:00 2001 From: Lovisa Berggren Date: Mon, 13 Jan 2025 17:02:22 +0000 Subject: [PATCH 01/13] CLOUDP-292068: Remove x-xgen-IPA-exception from version split OASes --- .../cli/internal/openapi/filter/extension.go | 81 +++++++- .../internal/openapi/filter/extension_test.go | 195 ++++++++++++++++++ tools/cli/internal/openapi/openapi3.go | 2 +- 3 files changed, 276 insertions(+), 2 deletions(-) diff --git a/tools/cli/internal/openapi/filter/extension.go b/tools/cli/internal/openapi/filter/extension.go index f7c85a25b0..ec6db8b5ed 100644 --- a/tools/cli/internal/openapi/filter/extension.go +++ b/tools/cli/internal/openapi/filter/extension.go @@ -21,7 +21,7 @@ import ( "github.com/mongodb/openapi/tools/cli/internal/apiversion" ) -// Filter: ExtensionFilter is a filter that updates the x-sunset and x-xgen-version extensions to a date string +// Filter: ExtensionFilter is a filter that deleted the x-xgen-ipa-exception extensions, updates the x-sunset and x-xgen-version extensions to a date string // and deletes the x-sunset extension if the latest matched version is deprecated by hidden versions // for the target environment type ExtensionFilter struct { @@ -31,6 +31,7 @@ type ExtensionFilter struct { const sunsetExtension = "x-sunset" const xGenExtension = "x-xgen-version" +const ipaExceptionExtension = "x-xgen-IPA-exception" const format = "2006-01-02T15:04:05Z07:00" func (f *ExtensionFilter) Apply() error { @@ -39,6 +40,7 @@ func (f *ExtensionFilter) Apply() error { continue } updateExtensionToDateString(pathItem.Extensions) + deleteIpaExceptionExtension(pathItem.Extensions) for _, operation := range pathItem.Operations() { if operation == nil { @@ -46,6 +48,18 @@ func (f *ExtensionFilter) Apply() error { } updateExtensionToDateString(operation.Extensions) + deleteIpaExceptionExtension(operation.Extensions) + + for _, parameter := range operation.Parameters { + if parameter.Value == nil || parameter.Value.Schema == nil { + continue + } + deleteIpaExceptionExtension(parameter.Value.Schema.Extensions) + if parameter.Value.Schema.Value == nil { + continue + } + deleteIpaExceptionExtension(parameter.Value.Schema.Value.Extensions) + } latestVersionMatch, err := apiversion.FindLatestContentVersionMatched(operation, f.metadata.targetVersion) if err != nil { @@ -58,12 +72,14 @@ func (f *ExtensionFilter) Apply() error { } updateExtensionToDateString(response.Extensions) + deleteIpaExceptionExtension(response.Extensions) if response.Value == nil { continue } updateExtensionToDateString(response.Value.Extensions) + deleteIpaExceptionExtension(response.Value.Extensions) if response.Value.Content == nil { continue @@ -81,6 +97,61 @@ func (f *ExtensionFilter) Apply() error { f.deleteSunsetIfDeprecatedByHiddenVersions(latestVersionMatch, request.Value.Content) } } + for _, tag := range f.oas.Tags { + if tag != nil { + deleteIpaExceptionExtension(tag.Extensions) + } + } + if f.oas.Components != nil { + for _, schema := range f.oas.Components.Schemas { + if schema != nil { + deleteIpaExceptionExtension(schema.Extensions) + } + if schema.Value != nil { + deleteIpaExceptionExtension(schema.Value.Extensions) + for _, allOf := range schema.Value.AllOf { + if allOf.Value == nil { + continue + } + for _, property := range allOf.Value.Properties { + if property.Value != nil { + deleteIpaExceptionExtension(property.Value.Extensions) + } + } + } + for _, anyOf := range schema.Value.AnyOf { + if anyOf.Value == nil { + continue + } + for _, property := range anyOf.Value.Properties { + if property.Value != nil { + deleteIpaExceptionExtension(property.Value.Extensions) + } + } + } + for _, oneOf := range schema.Value.OneOf { + if oneOf.Value == nil { + continue + } + for _, property := range oneOf.Value.Properties { + if property.Value != nil { + deleteIpaExceptionExtension(property.Value.Extensions) + } + } + } + for _, property := range schema.Value.Properties { + if property.Value != nil { + deleteIpaExceptionExtension(property.Value.Extensions) + } + } + } + } + for _, parameter := range f.oas.Components.Parameters { + if parameter != nil { + deleteIpaExceptionExtension(parameter.Extensions) + } + } + } return nil } @@ -101,6 +172,14 @@ func updateExtensionToDateString(extensions map[string]any) { } } +func deleteIpaExceptionExtension(extensions map[string]any) { + if extensions == nil || extensions[ipaExceptionExtension] == nil { + return + } + + delete(extensions, ipaExceptionExtension) +} + func (f *ExtensionFilter) updateToDateString(content openapi3.Content) { for _, mediaType := range content { if mediaType.Extensions == nil { diff --git a/tools/cli/internal/openapi/filter/extension_test.go b/tools/cli/internal/openapi/filter/extension_test.go index 295d1006b4..906db0bb4e 100644 --- a/tools/cli/internal/openapi/filter/extension_test.go +++ b/tools/cli/internal/openapi/filter/extension_test.go @@ -77,6 +77,80 @@ func TestXSunsetFilter_removeSunset(t *testing.T) { } } +func TestExtensionFilter_removeIpaException(t *testing.T) { + version, err := apiversion.New(apiversion.WithVersion("2023-01-01")) + contentKey := fmt.Sprintf("application/vnd.atlas.%s+json", version) + + require.NoError(t, err) + oas := getOasIpaExceptions() + + filter := &ExtensionFilter{ + oas: oas, + metadata: &Metadata{targetVersion: version, targetEnv: "dev"}, + } + require.NoError(t, filter.Apply()) + + operationParameter := oas.Paths.Find("/path").Get.Parameters[0] + assert.NotNil(t, operationParameter) + assert.Nil(t, operationParameter.Extensions[ipaExceptionExtension]) + + operationParameterSchema := oas.Paths.Find("/path").Get.Parameters[0].Value.Schema + assert.NotNil(t, operationParameterSchema) + assert.Nil(t, operationParameterSchema.Extensions[ipaExceptionExtension]) + + operation := oas.Paths.Find("/path").Get + assert.NotNil(t, operation) + assert.Nil(t, operation.Extensions[ipaExceptionExtension]) + + responseSchema := oas.Paths.Find("/path").Get.Responses.Map()["200"].Value.Content.Get(contentKey).Schema + assert.NotNil(t, responseSchema) + assert.Nil(t, responseSchema.Extensions[ipaExceptionExtension]) + + responseValue := oas.Paths.Find("/path").Get.Responses.Map()["200"].Value + assert.NotNil(t, responseValue) + assert.Nil(t, responseValue.Extensions[ipaExceptionExtension]) + + response := oas.Paths.Find("/path").Get.Responses.Map()["200"] + assert.NotNil(t, response) + assert.Nil(t, response.Extensions[ipaExceptionExtension]) + + path := oas.Paths.Find("/path") + assert.NotNil(t, path) + assert.Nil(t, path.Extensions[ipaExceptionExtension]) + + tag := oas.Tags.Get("tag") + assert.NotNil(t, tag) + assert.Nil(t, tag.Extensions[ipaExceptionExtension]) + + componentParameter := oas.Components.Parameters["parameter"] + assert.NotNil(t, componentParameter) + assert.Nil(t, componentParameter.Extensions[ipaExceptionExtension]) + + componentSchema := oas.Components.Schemas["schema"] + assert.NotNil(t, componentSchema) + assert.Nil(t, componentSchema.Extensions[ipaExceptionExtension]) + + componentSchemaValue := oas.Components.Schemas["schema"].Value + assert.NotNil(t, componentSchemaValue) + assert.Nil(t, componentSchemaValue.Extensions[ipaExceptionExtension]) + + componentSchemaProperty := oas.Components.Schemas["schema"].Value.Properties["property"] + assert.NotNil(t, componentSchemaProperty) + assert.Nil(t, componentSchemaProperty.Extensions[ipaExceptionExtension]) + + componentAllOfSchemaProperty := oas.Components.Schemas["schemaAllOf"].Value.AllOf[0].Value.Properties["property"] + assert.NotNil(t, componentAllOfSchemaProperty) + assert.Nil(t, componentAllOfSchemaProperty.Extensions[ipaExceptionExtension]) + + componentAnyOfSchemaProperty := oas.Components.Schemas["schemaAnyOf"].Value.AnyOf[0].Value.Properties["property"] + assert.NotNil(t, componentAnyOfSchemaProperty) + assert.Nil(t, componentAnyOfSchemaProperty.Extensions[ipaExceptionExtension]) + + componentOneOfSchemaProperty := oas.Components.Schemas["schemaOneOf"].Value.OneOf[0].Value.Properties["property"] + assert.NotNil(t, componentOneOfSchemaProperty) + assert.Nil(t, componentOneOfSchemaProperty.Extensions[ipaExceptionExtension]) +} + func getOasSunset() *openapi3.T { oas := &openapi3.T{} oas.Paths = &openapi3.Paths{} @@ -144,3 +218,124 @@ func getOasSunset() *openapi3.T { oas.Paths.Set("/path", &openapi3.PathItem{Get: operation}) return oas } + +func getOasIpaExceptions() *openapi3.T { + extension := map[string]interface{}{ + ipaExceptionExtension: map[string]string{"IPA-104-resource-has-GET": "reason"}, + } + + oas := &openapi3.T{} + oas.Paths = &openapi3.Paths{} + oas.Tags = make([]*openapi3.Tag, 0) + oas.Components = &openapi3.Components{} + + parameters := make(openapi3.Parameters, 0) + parameters = append(parameters, &openapi3.ParameterRef{ + Value: &openapi3.Parameter{ + Description: "description", + Schema: &openapi3.SchemaRef{ + Value: &openapi3.Schema{ + Description: "description", + }, + Extensions: extension, + }, + }, + Extensions: extension}) + + operation := &openapi3.Operation{ + Responses: &openapi3.Responses{}, + Parameters: parameters, + Extensions: extension, + } + + operation.Responses.Set("200", &openapi3.ResponseRef{ + Value: &openapi3.Response{ + Content: map[string]*openapi3.MediaType{ + "application/vnd.atlas.2023-01-01+json": { + Schema: &openapi3.SchemaRef{ + Value: &openapi3.Schema{ + Description: "description", + }, + Extensions: extension, + }, + }, + }, + Extensions: extension, + }, + Extensions: extension, + }) + + oas.Paths.Set("/path", &openapi3.PathItem{ + Get: operation, + Extensions: extension}) + + oas.Tags = append(oas.Tags, &openapi3.Tag{ + Name: "tag", + Description: "description", + Extensions: extension, + }) + + multipleSchemas := make(openapi3.SchemaRefs, 0) + + multipleSchemas = append(multipleSchemas, &openapi3.SchemaRef{ + Value: &openapi3.Schema{ + Properties: map[string]*openapi3.SchemaRef{ + "property": { + Value: &openapi3.Schema{ + Description: "description", + Extensions: extension, + }, + }, + }, + }, + }) + + components := &openapi3.Components{ + Parameters: map[string]*openapi3.ParameterRef{ + "parameter": { + Value: &openapi3.Parameter{ + Description: "description", + }, + Extensions: extension, + }, + }, + Schemas: map[string]*openapi3.SchemaRef{ + "schema": { + Value: &openapi3.Schema{ + Description: "description", + Properties: map[string]*openapi3.SchemaRef{ + "property": { + Value: &openapi3.Schema{ + Description: "description", + Extensions: extension, + }, + }, + }, + Extensions: extension, + }, + Extensions: extension, + }, + "schemaAllOf": { + Value: &openapi3.Schema{ + Description: "description", + AllOf: multipleSchemas, + }, + }, + "schemaAnyOf": { + Value: &openapi3.Schema{ + Description: "description", + AnyOf: multipleSchemas, + }, + }, + "schemaOneOf": { + Value: &openapi3.Schema{ + Description: "description", + OneOf: multipleSchemas, + }, + }, + }} + + oas.Components = components + + return oas +} diff --git a/tools/cli/internal/openapi/openapi3.go b/tools/cli/internal/openapi/openapi3.go index 15da0e635c..0bf01b790c 100644 --- a/tools/cli/internal/openapi/openapi3.go +++ b/tools/cli/internal/openapi/openapi3.go @@ -48,10 +48,10 @@ func (o *OpenAPI3) WithExcludedPrivatePaths() *OpenAPI3 { func (o *OpenAPI3) CreateOpenAPISpecFromPath(path string) (*load.SpecInfo, error) { o.Loader.IsExternalRefsAllowed = o.IsExternalRefsAllowed spec, err := load.NewSpecInfo(o.Loader, load.NewSource(path)) - spec.Url = path if err != nil { return nil, err } + spec.Url = path if o.ExcludePrivatePaths { removePrivatePaths(spec.Spec) From 5863688ab94cb773dae3e1445a04998c56086a04 Mon Sep 17 00:00:00 2001 From: Lovisa Berggren Date: Mon, 13 Jan 2025 17:11:01 +0000 Subject: [PATCH 02/13] CLOUDP-292068: Lint --- tools/cli/internal/openapi/filter/extension.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/cli/internal/openapi/filter/extension.go b/tools/cli/internal/openapi/filter/extension.go index ec6db8b5ed..e2db962fbe 100644 --- a/tools/cli/internal/openapi/filter/extension.go +++ b/tools/cli/internal/openapi/filter/extension.go @@ -21,8 +21,8 @@ import ( "github.com/mongodb/openapi/tools/cli/internal/apiversion" ) -// Filter: ExtensionFilter is a filter that deleted the x-xgen-ipa-exception extensions, updates the x-sunset and x-xgen-version extensions to a date string -// and deletes the x-sunset extension if the latest matched version is deprecated by hidden versions +// Filter: ExtensionFilter is a filter that deleted the x-xgen-ipa-exception extensions, updates the x-sunset and x-xgen-version +// extensions to a date string and deletes the x-sunset extension if the latest matched version is deprecated by hidden versions // for the target environment type ExtensionFilter struct { oas *openapi3.T From a3bddf3ddd5f9254388361a13d7e197788c13c5d Mon Sep 17 00:00:00 2001 From: Lovisa Berggren Date: Mon, 13 Jan 2025 17:12:04 +0000 Subject: [PATCH 03/13] CLOUDP-292068: Gen docs --- tools/cli/internal/openapi/filter/README.md | 2 +- tools/cli/internal/openapi/filter/mock_filter.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/cli/internal/openapi/filter/README.md b/tools/cli/internal/openapi/filter/README.md index 3649d28371..2a86270161 100644 --- a/tools/cli/internal/openapi/filter/README.md +++ b/tools/cli/internal/openapi/filter/README.md @@ -8,7 +8,7 @@ The Atlas Admin API OpenAPI specifications are used not only to document REST en - Filtering per version, so that only the endpoints that are available in that version are shown. ## What filters are available? ### List of filters -[ExtensionFilter is a filter that updates the x-sunset and x-xgen-version extensions to a date string](../internal/openapi/filter/extension.go?plain=1#L24) +[ExtensionFilter is a filter that deleted the x-xgen-ipa-exception extensions, updates the x-sunset and x-xgen-version](../internal/openapi/filter/extension.go?plain=1#L24) [HiddenEnvsFilter is a filter that removes paths, operations,](../internal/openapi/filter/hidden_envs.go?plain=1#L28) [InfoFilter is a filter that modifies the Info object in the OpenAPI spec.](../internal/openapi/filter/info.go?plain=1#L23) [OperationsFilter is a filter that removes the x-xgen-owner-team extension from operations](../internal/openapi/filter/operations.go?plain=1#L20) diff --git a/tools/cli/internal/openapi/filter/mock_filter.go b/tools/cli/internal/openapi/filter/mock_filter.go index 30d17193b6..8785d229f7 100644 --- a/tools/cli/internal/openapi/filter/mock_filter.go +++ b/tools/cli/internal/openapi/filter/mock_filter.go @@ -19,6 +19,7 @@ import ( type MockFilter struct { ctrl *gomock.Controller recorder *MockFilterMockRecorder + isgomock struct{} } // MockFilterMockRecorder is the mock recorder for MockFilter. From df83b4052d0f9fa958d80b38c962e32f7074e653 Mon Sep 17 00:00:00 2001 From: Lovisa Berggren Date: Mon, 13 Jan 2025 17:42:01 +0000 Subject: [PATCH 04/13] CLOUDP-292068: Extract functions --- .../cli/internal/openapi/filter/extension.go | 114 ++++++++++-------- 1 file changed, 62 insertions(+), 52 deletions(-) diff --git a/tools/cli/internal/openapi/filter/extension.go b/tools/cli/internal/openapi/filter/extension.go index e2db962fbe..d5b4c8b99f 100644 --- a/tools/cli/internal/openapi/filter/extension.go +++ b/tools/cli/internal/openapi/filter/extension.go @@ -97,60 +97,11 @@ func (f *ExtensionFilter) Apply() error { f.deleteSunsetIfDeprecatedByHiddenVersions(latestVersionMatch, request.Value.Content) } } - for _, tag := range f.oas.Tags { - if tag != nil { - deleteIpaExceptionExtension(tag.Extensions) - } + if f.oas.Tags != nil { + updateExtensionsForTags(f.oas.Tags) } if f.oas.Components != nil { - for _, schema := range f.oas.Components.Schemas { - if schema != nil { - deleteIpaExceptionExtension(schema.Extensions) - } - if schema.Value != nil { - deleteIpaExceptionExtension(schema.Value.Extensions) - for _, allOf := range schema.Value.AllOf { - if allOf.Value == nil { - continue - } - for _, property := range allOf.Value.Properties { - if property.Value != nil { - deleteIpaExceptionExtension(property.Value.Extensions) - } - } - } - for _, anyOf := range schema.Value.AnyOf { - if anyOf.Value == nil { - continue - } - for _, property := range anyOf.Value.Properties { - if property.Value != nil { - deleteIpaExceptionExtension(property.Value.Extensions) - } - } - } - for _, oneOf := range schema.Value.OneOf { - if oneOf.Value == nil { - continue - } - for _, property := range oneOf.Value.Properties { - if property.Value != nil { - deleteIpaExceptionExtension(property.Value.Extensions) - } - } - } - for _, property := range schema.Value.Properties { - if property.Value != nil { - deleteIpaExceptionExtension(property.Value.Extensions) - } - } - } - } - for _, parameter := range f.oas.Components.Parameters { - if parameter != nil { - deleteIpaExceptionExtension(parameter.Extensions) - } - } + updateExtensionsForComponents(*f.oas.Components) } return nil } @@ -172,6 +123,65 @@ func updateExtensionToDateString(extensions map[string]any) { } } +func updateExtensionsForComponents(components openapi3.Components) { + for _, schema := range components.Schemas { + if schema != nil { + deleteIpaExceptionExtension(schema.Extensions) + } + if schema.Value != nil { + deleteIpaExceptionExtension(schema.Value.Extensions) + for _, allOf := range schema.Value.AllOf { + if allOf.Value == nil { + continue + } + for _, property := range allOf.Value.Properties { + if property.Value != nil { + deleteIpaExceptionExtension(property.Value.Extensions) + } + } + } + for _, anyOf := range schema.Value.AnyOf { + if anyOf.Value == nil { + continue + } + for _, property := range anyOf.Value.Properties { + if property.Value != nil { + deleteIpaExceptionExtension(property.Value.Extensions) + } + } + } + for _, oneOf := range schema.Value.OneOf { + if oneOf.Value == nil { + continue + } + for _, property := range oneOf.Value.Properties { + if property.Value != nil { + deleteIpaExceptionExtension(property.Value.Extensions) + } + } + } + for _, property := range schema.Value.Properties { + if property.Value != nil { + deleteIpaExceptionExtension(property.Value.Extensions) + } + } + } + } + for _, parameter := range components.Parameters { + if parameter != nil { + deleteIpaExceptionExtension(parameter.Extensions) + } + } +} + +func updateExtensionsForTags(tags openapi3.Tags) { + for _, tag := range tags { + if tag != nil { + deleteIpaExceptionExtension(tag.Extensions) + } + } +} + func deleteIpaExceptionExtension(extensions map[string]any) { if extensions == nil || extensions[ipaExceptionExtension] == nil { return From 7149e88f6124390a7e47826a72ef5c9525e20f55 Mon Sep 17 00:00:00 2001 From: Lovisa Berggren Date: Mon, 13 Jan 2025 17:45:42 +0000 Subject: [PATCH 05/13] CLOUDP-292068: Lint --- tools/cli/internal/openapi/filter/extension.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/cli/internal/openapi/filter/extension.go b/tools/cli/internal/openapi/filter/extension.go index d5b4c8b99f..f4fce90cff 100644 --- a/tools/cli/internal/openapi/filter/extension.go +++ b/tools/cli/internal/openapi/filter/extension.go @@ -98,10 +98,10 @@ func (f *ExtensionFilter) Apply() error { } } if f.oas.Tags != nil { - updateExtensionsForTags(f.oas.Tags) + updateExtensionsForTags(&f.oas.Tags) } if f.oas.Components != nil { - updateExtensionsForComponents(*f.oas.Components) + updateExtensionsForComponents(f.oas.Components) } return nil } @@ -123,7 +123,7 @@ func updateExtensionToDateString(extensions map[string]any) { } } -func updateExtensionsForComponents(components openapi3.Components) { +func updateExtensionsForComponents(components *openapi3.Components) { for _, schema := range components.Schemas { if schema != nil { deleteIpaExceptionExtension(schema.Extensions) @@ -174,8 +174,8 @@ func updateExtensionsForComponents(components openapi3.Components) { } } -func updateExtensionsForTags(tags openapi3.Tags) { - for _, tag := range tags { +func updateExtensionsForTags(tags *openapi3.Tags) { + for _, tag := range *tags { if tag != nil { deleteIpaExceptionExtension(tag.Extensions) } From fc93775a38a4f7f13a70f41d99eb8492b4653672 Mon Sep 17 00:00:00 2001 From: Lovisa Berggren Date: Tue, 14 Jan 2025 12:03:36 +0000 Subject: [PATCH 06/13] CLOUDP-292068: Comment fix --- tools/cli/internal/openapi/filter/README.md | 2 +- tools/cli/internal/openapi/filter/extension.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/cli/internal/openapi/filter/README.md b/tools/cli/internal/openapi/filter/README.md index 2a86270161..3981b6c1a0 100644 --- a/tools/cli/internal/openapi/filter/README.md +++ b/tools/cli/internal/openapi/filter/README.md @@ -8,7 +8,7 @@ The Atlas Admin API OpenAPI specifications are used not only to document REST en - Filtering per version, so that only the endpoints that are available in that version are shown. ## What filters are available? ### List of filters -[ExtensionFilter is a filter that deleted the x-xgen-ipa-exception extensions, updates the x-sunset and x-xgen-version](../internal/openapi/filter/extension.go?plain=1#L24) +[ExtensionFilter is a filter that deletes the x-xgen-ipa-exception extensions, updates the x-sunset and x-xgen-version](../internal/openapi/filter/extension.go?plain=1#L24) [HiddenEnvsFilter is a filter that removes paths, operations,](../internal/openapi/filter/hidden_envs.go?plain=1#L28) [InfoFilter is a filter that modifies the Info object in the OpenAPI spec.](../internal/openapi/filter/info.go?plain=1#L23) [OperationsFilter is a filter that removes the x-xgen-owner-team extension from operations](../internal/openapi/filter/operations.go?plain=1#L20) diff --git a/tools/cli/internal/openapi/filter/extension.go b/tools/cli/internal/openapi/filter/extension.go index f4fce90cff..13dfa90622 100644 --- a/tools/cli/internal/openapi/filter/extension.go +++ b/tools/cli/internal/openapi/filter/extension.go @@ -21,7 +21,7 @@ import ( "github.com/mongodb/openapi/tools/cli/internal/apiversion" ) -// Filter: ExtensionFilter is a filter that deleted the x-xgen-ipa-exception extensions, updates the x-sunset and x-xgen-version +// Filter: ExtensionFilter is a filter that deletes the x-xgen-ipa-exception extensions, updates the x-sunset and x-xgen-version // extensions to a date string and deletes the x-sunset extension if the latest matched version is deprecated by hidden versions // for the target environment type ExtensionFilter struct { From a22f7d5cfd8374d03acd5c196f95207fa99f2195 Mon Sep 17 00:00:00 2001 From: Lovisa Berggren Date: Tue, 14 Jan 2025 12:28:14 +0000 Subject: [PATCH 07/13] CLOUDP-292068: Add case for requestBody --- .../cli/internal/openapi/filter/extension.go | 95 +++++++++++-------- .../internal/openapi/filter/extension_test.go | 36 ++++++- 2 files changed, 87 insertions(+), 44 deletions(-) diff --git a/tools/cli/internal/openapi/filter/extension.go b/tools/cli/internal/openapi/filter/extension.go index 13dfa90622..f0b23492be 100644 --- a/tools/cli/internal/openapi/filter/extension.go +++ b/tools/cli/internal/openapi/filter/extension.go @@ -66,6 +66,15 @@ func (f *ExtensionFilter) Apply() error { return err } + if operation.RequestBody != nil { + deleteIpaExceptionExtension(operation.RequestBody.Extensions) + _, contentsInVersion := getVersionsInContentType(operation.RequestBody.Value.Content) + for _, content := range contentsInVersion { + deleteIpaExceptionExtension(content.Extensions) + updateExtensionsForSchema(content.Schema) + } + } + for _, response := range operation.Responses.Map() { if response == nil { continue @@ -125,47 +134,7 @@ func updateExtensionToDateString(extensions map[string]any) { func updateExtensionsForComponents(components *openapi3.Components) { for _, schema := range components.Schemas { - if schema != nil { - deleteIpaExceptionExtension(schema.Extensions) - } - if schema.Value != nil { - deleteIpaExceptionExtension(schema.Value.Extensions) - for _, allOf := range schema.Value.AllOf { - if allOf.Value == nil { - continue - } - for _, property := range allOf.Value.Properties { - if property.Value != nil { - deleteIpaExceptionExtension(property.Value.Extensions) - } - } - } - for _, anyOf := range schema.Value.AnyOf { - if anyOf.Value == nil { - continue - } - for _, property := range anyOf.Value.Properties { - if property.Value != nil { - deleteIpaExceptionExtension(property.Value.Extensions) - } - } - } - for _, oneOf := range schema.Value.OneOf { - if oneOf.Value == nil { - continue - } - for _, property := range oneOf.Value.Properties { - if property.Value != nil { - deleteIpaExceptionExtension(property.Value.Extensions) - } - } - } - for _, property := range schema.Value.Properties { - if property.Value != nil { - deleteIpaExceptionExtension(property.Value.Extensions) - } - } - } + updateExtensionsForSchema(schema) } for _, parameter := range components.Parameters { if parameter != nil { @@ -182,6 +151,50 @@ func updateExtensionsForTags(tags *openapi3.Tags) { } } +func updateExtensionsForSchema(schema *openapi3.SchemaRef) { + if schema != nil { + deleteIpaExceptionExtension(schema.Extensions) + } + if schema.Value != nil { + deleteIpaExceptionExtension(schema.Value.Extensions) + for _, allOf := range schema.Value.AllOf { + if allOf.Value == nil { + continue + } + for _, property := range allOf.Value.Properties { + if property.Value != nil { + deleteIpaExceptionExtension(property.Value.Extensions) + } + } + } + for _, anyOf := range schema.Value.AnyOf { + if anyOf.Value == nil { + continue + } + for _, property := range anyOf.Value.Properties { + if property.Value != nil { + deleteIpaExceptionExtension(property.Value.Extensions) + } + } + } + for _, oneOf := range schema.Value.OneOf { + if oneOf.Value == nil { + continue + } + for _, property := range oneOf.Value.Properties { + if property.Value != nil { + deleteIpaExceptionExtension(property.Value.Extensions) + } + } + } + for _, property := range schema.Value.Properties { + if property.Value != nil { + deleteIpaExceptionExtension(property.Value.Extensions) + } + } + } +} + func deleteIpaExceptionExtension(extensions map[string]any) { if extensions == nil || extensions[ipaExceptionExtension] == nil { return diff --git a/tools/cli/internal/openapi/filter/extension_test.go b/tools/cli/internal/openapi/filter/extension_test.go index 906db0bb4e..5b18176648 100644 --- a/tools/cli/internal/openapi/filter/extension_test.go +++ b/tools/cli/internal/openapi/filter/extension_test.go @@ -114,6 +114,18 @@ func TestExtensionFilter_removeIpaException(t *testing.T) { assert.NotNil(t, response) assert.Nil(t, response.Extensions[ipaExceptionExtension]) + requestBody := oas.Paths.Find("/path").Get.RequestBody + assert.NotNil(t, requestBody) + assert.Nil(t, requestBody.Extensions[ipaExceptionExtension]) + + requestBodyContent := oas.Paths.Find("/path").Get.RequestBody.Value.Content.Get(contentKey) + assert.NotNil(t, requestBodyContent) + assert.Nil(t, requestBodyContent.Extensions[ipaExceptionExtension]) + + requestBodyContentSchema := oas.Paths.Find("/path").Get.RequestBody.Value.Content.Get(contentKey).Schema + assert.NotNil(t, requestBodyContentSchema) + assert.Nil(t, requestBodyContentSchema.Extensions[ipaExceptionExtension]) + path := oas.Paths.Find("/path") assert.NotNil(t, path) assert.Nil(t, path.Extensions[ipaExceptionExtension]) @@ -243,9 +255,10 @@ func getOasIpaExceptions() *openapi3.T { Extensions: extension}) operation := &openapi3.Operation{ - Responses: &openapi3.Responses{}, - Parameters: parameters, - Extensions: extension, + Responses: &openapi3.Responses{}, + RequestBody: &openapi3.RequestBodyRef{}, + Parameters: parameters, + Extensions: extension, } operation.Responses.Set("200", &openapi3.ResponseRef{ @@ -265,6 +278,23 @@ func getOasIpaExceptions() *openapi3.T { Extensions: extension, }) + operation.RequestBody = &openapi3.RequestBodyRef{ + Value: &openapi3.RequestBody{ + Content: map[string]*openapi3.MediaType{ + "application/vnd.atlas.2023-01-01+json": { + Schema: &openapi3.SchemaRef{ + Value: &openapi3.Schema{ + Description: "description", + }, + Extensions: extension, + }, + Extensions: extension, + }, + }, + }, + Extensions: extension, + } + oas.Paths.Set("/path", &openapi3.PathItem{ Get: operation, Extensions: extension}) From a345b322eb8c7d2189584c2c079d157e08bbede6 Mon Sep 17 00:00:00 2001 From: Lovisa Berggren Date: Tue, 14 Jan 2025 14:02:37 +0000 Subject: [PATCH 08/13] CLOUDP-292068: Group consts --- tools/cli/internal/openapi/filter/extension.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/cli/internal/openapi/filter/extension.go b/tools/cli/internal/openapi/filter/extension.go index f0b23492be..06dbd37a13 100644 --- a/tools/cli/internal/openapi/filter/extension.go +++ b/tools/cli/internal/openapi/filter/extension.go @@ -29,10 +29,12 @@ type ExtensionFilter struct { metadata *Metadata } -const sunsetExtension = "x-sunset" -const xGenExtension = "x-xgen-version" -const ipaExceptionExtension = "x-xgen-IPA-exception" -const format = "2006-01-02T15:04:05Z07:00" +const ( + sunsetExtension = "x-sunset" + xGenExtension = "x-xgen-version" + ipaExceptionExtension = "x-xgen-IPA-exception" + format = "2006-01-02T15:04:05Z07:00" +) func (f *ExtensionFilter) Apply() error { for _, pathItem := range f.oas.Paths.Map() { From 23e9da2e13379e845379d988a8f21d7eff548aea Mon Sep 17 00:00:00 2001 From: Lovisa Berggren Date: Tue, 14 Jan 2025 14:02:47 +0000 Subject: [PATCH 09/13] CLOUDP-292068: Test cases --- .../internal/openapi/filter/extension_test.go | 176 +++++++++++------- 1 file changed, 104 insertions(+), 72 deletions(-) diff --git a/tools/cli/internal/openapi/filter/extension_test.go b/tools/cli/internal/openapi/filter/extension_test.go index 5b18176648..4539390fab 100644 --- a/tools/cli/internal/openapi/filter/extension_test.go +++ b/tools/cli/internal/openapi/filter/extension_test.go @@ -78,11 +78,9 @@ func TestXSunsetFilter_removeSunset(t *testing.T) { } func TestExtensionFilter_removeIpaException(t *testing.T) { + oas := getOasIpaExceptions() version, err := apiversion.New(apiversion.WithVersion("2023-01-01")) - contentKey := fmt.Sprintf("application/vnd.atlas.%s+json", version) - require.NoError(t, err) - oas := getOasIpaExceptions() filter := &ExtensionFilter{ oas: oas, @@ -90,77 +88,111 @@ func TestExtensionFilter_removeIpaException(t *testing.T) { } require.NoError(t, filter.Apply()) - operationParameter := oas.Paths.Find("/path").Get.Parameters[0] - assert.NotNil(t, operationParameter) - assert.Nil(t, operationParameter.Extensions[ipaExceptionExtension]) - - operationParameterSchema := oas.Paths.Find("/path").Get.Parameters[0].Value.Schema - assert.NotNil(t, operationParameterSchema) - assert.Nil(t, operationParameterSchema.Extensions[ipaExceptionExtension]) - - operation := oas.Paths.Find("/path").Get - assert.NotNil(t, operation) - assert.Nil(t, operation.Extensions[ipaExceptionExtension]) - - responseSchema := oas.Paths.Find("/path").Get.Responses.Map()["200"].Value.Content.Get(contentKey).Schema - assert.NotNil(t, responseSchema) - assert.Nil(t, responseSchema.Extensions[ipaExceptionExtension]) - - responseValue := oas.Paths.Find("/path").Get.Responses.Map()["200"].Value - assert.NotNil(t, responseValue) - assert.Nil(t, responseValue.Extensions[ipaExceptionExtension]) - - response := oas.Paths.Find("/path").Get.Responses.Map()["200"] - assert.NotNil(t, response) - assert.Nil(t, response.Extensions[ipaExceptionExtension]) - - requestBody := oas.Paths.Find("/path").Get.RequestBody - assert.NotNil(t, requestBody) - assert.Nil(t, requestBody.Extensions[ipaExceptionExtension]) - - requestBodyContent := oas.Paths.Find("/path").Get.RequestBody.Value.Content.Get(contentKey) - assert.NotNil(t, requestBodyContent) - assert.Nil(t, requestBodyContent.Extensions[ipaExceptionExtension]) - - requestBodyContentSchema := oas.Paths.Find("/path").Get.RequestBody.Value.Content.Get(contentKey).Schema - assert.NotNil(t, requestBodyContentSchema) - assert.Nil(t, requestBodyContentSchema.Extensions[ipaExceptionExtension]) - - path := oas.Paths.Find("/path") - assert.NotNil(t, path) - assert.Nil(t, path.Extensions[ipaExceptionExtension]) - - tag := oas.Tags.Get("tag") - assert.NotNil(t, tag) - assert.Nil(t, tag.Extensions[ipaExceptionExtension]) - - componentParameter := oas.Components.Parameters["parameter"] - assert.NotNil(t, componentParameter) - assert.Nil(t, componentParameter.Extensions[ipaExceptionExtension]) - - componentSchema := oas.Components.Schemas["schema"] - assert.NotNil(t, componentSchema) - assert.Nil(t, componentSchema.Extensions[ipaExceptionExtension]) - - componentSchemaValue := oas.Components.Schemas["schema"].Value - assert.NotNil(t, componentSchemaValue) - assert.Nil(t, componentSchemaValue.Extensions[ipaExceptionExtension]) - - componentSchemaProperty := oas.Components.Schemas["schema"].Value.Properties["property"] - assert.NotNil(t, componentSchemaProperty) - assert.Nil(t, componentSchemaProperty.Extensions[ipaExceptionExtension]) - - componentAllOfSchemaProperty := oas.Components.Schemas["schemaAllOf"].Value.AllOf[0].Value.Properties["property"] - assert.NotNil(t, componentAllOfSchemaProperty) - assert.Nil(t, componentAllOfSchemaProperty.Extensions[ipaExceptionExtension]) + contentKey := fmt.Sprintf("application/vnd.atlas.%s+json", version) - componentAnyOfSchemaProperty := oas.Components.Schemas["schemaAnyOf"].Value.AnyOf[0].Value.Properties["property"] - assert.NotNil(t, componentAnyOfSchemaProperty) - assert.Nil(t, componentAnyOfSchemaProperty.Extensions[ipaExceptionExtension]) + tests := []struct { + name string + component any + extension any + }{ + { + name: "operationParameter", + component: oas.Paths.Find("/path").Get.Parameters[0], + extension: oas.Paths.Find("/path").Get.Parameters[0].Extensions[ipaExceptionExtension], + }, + { + name: "operationParameterSchema", + component: oas.Paths.Find("/path").Get.Parameters[0].Value.Schema, + extension: oas.Paths.Find("/path").Get.Parameters[0].Value.Schema.Extensions[ipaExceptionExtension], + }, + { + name: "operation", + component: oas.Paths.Find("/path").Get, + extension: oas.Paths.Find("/path").Get.Extensions[ipaExceptionExtension], + }, + { + name: "responseSchema", + component: oas.Paths.Find("/path").Get.Responses.Map()["200"].Value.Content.Get(contentKey).Schema, + extension: oas.Paths.Find("/path").Get.Responses.Map()["200"].Value.Content.Get(contentKey).Schema.Extensions[ipaExceptionExtension], + }, + { + name: "responseValue", + component: oas.Paths.Find("/path").Get.Responses.Map()["200"].Value, + extension: oas.Paths.Find("/path").Get.Responses.Map()["200"].Value.Extensions[ipaExceptionExtension], + }, + { + name: "response", + component: oas.Paths.Find("/path").Get.Responses.Map()["200"], + extension: oas.Paths.Find("/path").Get.Responses.Map()["200"].Extensions[ipaExceptionExtension], + }, + { + name: "requestBody", + component: oas.Paths.Find("/path").Get.RequestBody, + extension: oas.Paths.Find("/path").Get.RequestBody.Extensions[ipaExceptionExtension], + }, + { + name: "requestBodyContent", + component: oas.Paths.Find("/path").Get.RequestBody.Value.Content.Get(contentKey), + extension: oas.Paths.Find("/path").Get.RequestBody.Value.Content.Get(contentKey).Extensions[ipaExceptionExtension], + }, + { + name: "requestBodyContentSchema", + component: oas.Paths.Find("/path").Get.RequestBody.Value.Content.Get(contentKey).Schema, + extension: oas.Paths.Find("/path").Get.RequestBody.Value.Content.Get(contentKey).Schema.Extensions[ipaExceptionExtension], + }, + { + name: "path", + component: oas.Paths.Find("/path"), + extension: oas.Paths.Find("/path").Extensions[ipaExceptionExtension], + }, + { + name: "tag", + component: oas.Tags.Get("tag"), + extension: oas.Tags.Get("tag").Extensions[ipaExceptionExtension], + }, + { + name: "componentParameter", + component: oas.Components.Parameters["parameter"], + extension: oas.Components.Parameters["parameter"].Extensions[ipaExceptionExtension], + }, + { + name: "componentSchema", + component: oas.Components.Schemas["schema"], + extension: oas.Components.Schemas["schema"].Extensions[ipaExceptionExtension], + }, + { + name: "componentSchemaValue", + component: oas.Components.Schemas["schema"].Value, + extension: oas.Components.Schemas["schema"].Value.Extensions[ipaExceptionExtension], + }, + { + name: "componentSchemaProperty", + component: oas.Components.Schemas["schema"].Value.Properties["property"], + extension: oas.Components.Schemas["schema"].Value.Properties["property"].Extensions[ipaExceptionExtension], + }, + { + name: "componentAllOfSchemaProperty", + component: oas.Components.Schemas["schemaAllOf"].Value.AllOf[0].Value.Properties["property"], + extension: oas.Components.Schemas["schemaAllOf"].Value.AllOf[0].Value.Properties["property"].Extensions[ipaExceptionExtension], + }, + { + name: "componentAnyOfSchemaProperty", + component: oas.Components.Schemas["schemaAnyOf"].Value.AnyOf[0].Value.Properties["property"], + extension: oas.Components.Schemas["schemaAnyOf"].Value.AnyOf[0].Value.Properties["property"].Extensions[ipaExceptionExtension], + }, + { + name: "componentOneOfSchemaProperty", + component: oas.Components.Schemas["schemaOneOf"].Value.OneOf[0].Value.Properties["property"], + extension: oas.Components.Schemas["schemaOneOf"].Value.OneOf[0].Value.Properties["property"].Extensions[ipaExceptionExtension], + }, + } - componentOneOfSchemaProperty := oas.Components.Schemas["schemaOneOf"].Value.OneOf[0].Value.Properties["property"] - assert.NotNil(t, componentOneOfSchemaProperty) - assert.Nil(t, componentOneOfSchemaProperty.Extensions[ipaExceptionExtension]) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.NotNil(t, tt.component) + assert.Nil(t, tt.extension) + }) + } } func getOasSunset() *openapi3.T { From cc0697f6ac8508efbf8d6df3503fc1981acd82f9 Mon Sep 17 00:00:00 2001 From: Lovisa Berggren Date: Tue, 14 Jan 2025 14:07:29 +0000 Subject: [PATCH 10/13] CLOUDP-292068: Revert one line --- tools/cli/internal/openapi/filter/mock_filter.go | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/cli/internal/openapi/filter/mock_filter.go b/tools/cli/internal/openapi/filter/mock_filter.go index 8785d229f7..30d17193b6 100644 --- a/tools/cli/internal/openapi/filter/mock_filter.go +++ b/tools/cli/internal/openapi/filter/mock_filter.go @@ -19,7 +19,6 @@ import ( type MockFilter struct { ctrl *gomock.Controller recorder *MockFilterMockRecorder - isgomock struct{} } // MockFilterMockRecorder is the mock recorder for MockFilter. From 17fb0c8db165c243a1dca7a48969173c15067ed1 Mon Sep 17 00:00:00 2001 From: Lovisa Berggren Date: Tue, 14 Jan 2025 17:00:23 +0000 Subject: [PATCH 11/13] CLOUDP-292068: Parallel --- tools/cli/internal/openapi/filter/extension_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/cli/internal/openapi/filter/extension_test.go b/tools/cli/internal/openapi/filter/extension_test.go index 4539390fab..2976d7be48 100644 --- a/tools/cli/internal/openapi/filter/extension_test.go +++ b/tools/cli/internal/openapi/filter/extension_test.go @@ -189,6 +189,7 @@ func TestExtensionFilter_removeIpaException(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() assert.NotNil(t, tt.component) assert.Nil(t, tt.extension) }) From 99f7709f15f8dbf545f75c82e989a75582571374 Mon Sep 17 00:00:00 2001 From: Lovisa Berggren Date: Tue, 14 Jan 2025 17:34:07 +0000 Subject: [PATCH 12/13] CLOUDP-292068: More functions --- .../cli/internal/openapi/filter/extension.go | 61 +++++++++++-------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/tools/cli/internal/openapi/filter/extension.go b/tools/cli/internal/openapi/filter/extension.go index 83020fd820..e3460f931d 100644 --- a/tools/cli/internal/openapi/filter/extension.go +++ b/tools/cli/internal/openapi/filter/extension.go @@ -53,27 +53,13 @@ func (f *ExtensionFilter) Apply() error { updateExtensionToDateString(operation.Extensions) deleteIpaExceptionExtension(operation.Extensions) - for _, parameter := range operation.Parameters { - if parameter.Value == nil || parameter.Value.Schema == nil { - continue - } - deleteIpaExceptionExtension(parameter.Value.Schema.Extensions) - if parameter.Value.Schema.Value == nil { - continue - } - deleteIpaExceptionExtension(parameter.Value.Schema.Value.Extensions) + if operation.Parameters != nil { + updateExtensionsForOperationParameters(operation.Parameters) } - latestVersionMatch := apiversion.FindLatestContentVersionMatched(operation, f.metadata.targetVersion) + updateExtensionsForRequestBody(operation.RequestBody) - if operation.RequestBody != nil { - deleteIpaExceptionExtension(operation.RequestBody.Extensions) - _, contentsInVersion := getVersionsInContentType(operation.RequestBody.Value.Content) - for _, content := range contentsInVersion { - deleteIpaExceptionExtension(content.Extensions) - updateExtensionsForSchema(content.Schema) - } - } + latestVersionMatch := apiversion.FindLatestContentVersionMatched(operation, f.metadata.targetVersion) for _, response := range operation.Responses.Map() { if response == nil { @@ -115,20 +101,28 @@ func (f *ExtensionFilter) Apply() error { return nil } -func updateExtensionToDateString(extensions map[string]any) { - if extensions == nil { +func updateExtensionsForRequestBody(requestBody *openapi3.RequestBodyRef) { + if requestBody == nil { return } + deleteIpaExceptionExtension(requestBody.Extensions) + _, contentsInVersion := getVersionsInContentType(requestBody.Value.Content) + for _, content := range contentsInVersion { + deleteIpaExceptionExtension(content.Extensions) + updateExtensionsForSchema(content.Schema) + } +} - for k, v := range extensions { - if k != sunsetExtension && k != xGenExtension { +func updateExtensionsForOperationParameters(parameters openapi3.Parameters) { + for _, parameter := range parameters { + if parameter.Value == nil || parameter.Value.Schema == nil { continue } - date, err := time.Parse(format, v.(string)) - if err != nil { + deleteIpaExceptionExtension(parameter.Value.Schema.Extensions) + if parameter.Value.Schema.Value == nil { continue } - extensions[k] = date.Format("2006-01-02") + deleteIpaExceptionExtension(parameter.Value.Schema.Value.Extensions) } } @@ -203,6 +197,23 @@ func deleteIpaExceptionExtension(extensions map[string]any) { delete(extensions, ipaExceptionExtension) } +func updateExtensionToDateString(extensions map[string]any) { + if extensions == nil { + return + } + + for k, v := range extensions { + if k != sunsetExtension && k != xGenExtension { + continue + } + date, err := time.Parse(format, v.(string)) + if err != nil { + continue + } + extensions[k] = date.Format("2006-01-02") + } +} + func (f *ExtensionFilter) updateToDateString(content openapi3.Content) { for _, mediaType := range content { if mediaType.Extensions == nil { From 2461711e0ca7b933979c309d85fe1dd03f9dc21e Mon Sep 17 00:00:00 2001 From: Lovisa Berggren Date: Wed, 15 Jan 2025 10:46:10 +0000 Subject: [PATCH 13/13] CLOUDP-292068: Lint fix --- tools/cli/internal/openapi/filter/extension_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/cli/internal/openapi/filter/extension_test.go b/tools/cli/internal/openapi/filter/extension_test.go index 81d199e895..1236be09f9 100644 --- a/tools/cli/internal/openapi/filter/extension_test.go +++ b/tools/cli/internal/openapi/filter/extension_test.go @@ -265,7 +265,7 @@ func getOasSunset() *openapi3.T { } func getOasIpaExceptions() *openapi3.T { - extension := map[string]interface{}{ + extension := map[string]any{ ipaExceptionExtension: map[string]string{"IPA-104-resource-has-GET": "reason"}, }