diff --git a/docs/learnservice_oas.yaml b/docs/learnservice_oas.yaml index 6d1e212..4e4bf05 100644 --- a/docs/learnservice_oas.yaml +++ b/docs/learnservice_oas.yaml @@ -30,7 +30,7 @@ servers: x-kong-tags: [ tag1, tag2 ] # specify the tags to use for each Kong entity generated. The tags can be overridden - # when doing the conversion. This can only be specified on document level. + # when doing the conversion. x-kong-service-defaults: # the defaults for the Kong services generated from 'servers' above @@ -140,6 +140,8 @@ paths: config: status_code: 403 message: So long and thanks for all the fish! + x-kong-tags: [ tag3, tag4 ] + # specify the tags to add for this specific route in addition to document level tags (if any) responses: '200': description: Successful operation diff --git a/openapi2kong/oas3_testfiles/17-tags-set.expected.json b/openapi2kong/oas3_testfiles/17-tags-set.expected.json new file mode 100644 index 0000000..526a4c4 --- /dev/null +++ b/openapi2kong/oas3_testfiles/17-tags-set.expected.json @@ -0,0 +1,36 @@ +{ + "_format_version": "3.0", + "services": [ + { + "host": "localhost", + "id": "0907c4ab-d9e4-5d21-813b-c57a97eeaad9", + "name": "simple-api-overview", + "path": "/", + "plugins": [], + "port": 443, + "protocol": "https", + "routes": [ + { + "id": "eee036de-517e-59cf-a2e0-17b3adfa31b5", + "methods": [ + "GET" + ], + "name": "simple-api-overview_opsid", + "paths": [ + "~/$" + ], + "plugins": [], + "regex_priority": 200, + "strip_path": false, + "tags": [ + "example-global-tag" + ] + } + ], + "tags": [ + "example-global-tag" + ] + } + ], + "upstreams": [] +} diff --git a/openapi2kong/oas3_testfiles/17-tags-set.yaml b/openapi2kong/oas3_testfiles/17-tags-set.yaml new file mode 100644 index 0000000..ac9a469 --- /dev/null +++ b/openapi2kong/oas3_testfiles/17-tags-set.yaml @@ -0,0 +1,19 @@ +openapi: '3.0.1' +info: + title: Simple API overview + version: v2 +servers: + - url: / + +x-kong-tags: + - example-global-tag + +paths: + /: + get: + operationId: OpsId + summary: List API versions + responses: + '200': + description: |- + 200 response diff --git a/openapi2kong/oas3_testfiles/17a-route-tags-set.expected.json b/openapi2kong/oas3_testfiles/17a-route-tags-set.expected.json new file mode 100644 index 0000000..d114373 --- /dev/null +++ b/openapi2kong/oas3_testfiles/17a-route-tags-set.expected.json @@ -0,0 +1,87 @@ +{ + "_format_version": "3.0", + "services": [ + { + "host": "localhost", + "id": "0907c4ab-d9e4-5d21-813b-c57a97eeaad9", + "name": "simple-api-overview", + "path": "/", + "plugins": [], + "port": 443, + "protocol": "https", + "routes": [ + { + "id": "038abf43-69d2-5b8b-962f-43804448847e", + "methods": [ + "GET" + ], + "name": "simple-api-overview_path1-has-route-tags", + "paths": [ + "~/path1$" + ], + "plugins": [], + "regex_priority": 200, + "strip_path": false, + "tags": [ + "example-global-tag", + "example-route-tag" + ] + }, + { + "id": "30086569-722d-570b-9f76-a06db016c8d3", + "methods": [ + "POST" + ], + "name": "simple-api-overview_path1-has-other-route-tags", + "paths": [ + "~/path1$" + ], + "plugins": [], + "regex_priority": 200, + "strip_path": false, + "tags": [ + "example-global-tag", + "example-route-tag-other" + ] + }, + { + "id": "c6326752-bb0c-56d1-a19a-bbfd081bfe2c", + "methods": [ + "GET" + ], + "name": "simple-api-overview_path2-no-route-tags", + "paths": [ + "~/path2$" + ], + "plugins": [], + "regex_priority": 200, + "strip_path": false, + "tags": [ + "example-global-tag" + ] + }, + { + "id": "2af580bd-b0c1-59bb-a691-bd65ca18c2ec", + "methods": [ + "POST" + ], + "name": "simple-api-overview_path2-has-route-tags", + "paths": [ + "~/path2$" + ], + "plugins": [], + "regex_priority": 200, + "strip_path": false, + "tags": [ + "example-global-tag", + "example-route-tag" + ] + } + ], + "tags": [ + "example-global-tag" + ] + } + ], + "upstreams": [] +} diff --git a/openapi2kong/oas3_testfiles/17a-route-tags-set.yaml b/openapi2kong/oas3_testfiles/17a-route-tags-set.yaml new file mode 100644 index 0000000..0957192 --- /dev/null +++ b/openapi2kong/oas3_testfiles/17a-route-tags-set.yaml @@ -0,0 +1,44 @@ +openapi: '3.0.1' +info: + title: Simple API overview + version: v2 +servers: + - url: / + +x-kong-tags: + - example-global-tag + +paths: + /path1: + get: + operationId: path1-has-route-tags + x-kong-tags: + - example-route-tag + responses: + '200': + description: |- + 200 response + post: + operationId: path1-has-other-route-tags + x-kong-tags: + - example-route-tag-other + responses: + '200': + description: |- + 200 response + + /path2: + get: + operationId: path2-no-route-tags + responses: + '200': + description: |- + 200 response + post: + operationId: path2-has-route-tags + x-kong-tags: + - example-route-tag + responses: + '200': + description: |- + 200 response diff --git a/openapi2kong/openapi2kong.go b/openapi2kong/openapi2kong.go index 55bd1b2..2266164 100644 --- a/openapi2kong/openapi2kong.go +++ b/openapi2kong/openapi2kong.go @@ -100,19 +100,19 @@ func sanitizeRegexCapture(varName string, insoCompat bool) string { // getKongTags returns the provided tags or if nil, then the `x-kong-tags` property, // validated to be a string array. If there is no error, then there will always be // an array returned for safe access later in the process. -func getKongTags(doc *openapi3.T, tagsProvided []string) ([]string, error) { +func getKongTags(extensionProps openapi3.ExtensionProps, tagsProvided []string) ([]string, error) { if tagsProvided != nil { // the provided tags take precedence, return them return tagsProvided, nil } - if doc.ExtensionProps.Extensions == nil || doc.ExtensionProps.Extensions["x-kong-tags"] == nil { + if extensionProps.Extensions == nil || extensionProps.Extensions["x-kong-tags"] == nil { // there is no extension, so return an empty array return make([]string, 0), nil } var tagsValue interface{} - err := json.Unmarshal(doc.ExtensionProps.Extensions["x-kong-tags"].(json.RawMessage), &tagsValue) + err := json.Unmarshal(extensionProps.Extensions["x-kong-tags"].(json.RawMessage), &tagsValue) if err != nil { return nil, fmt.Errorf("expected 'x-kong-tags' to be an array of strings: %w", err) } @@ -641,7 +641,7 @@ func Convert(content []byte, opts O2kOptions) (map[string]interface{}, error) { // // collect tags to use - if kongTags, err = getKongTags(doc, opts.Tags); err != nil { + if kongTags, err = getKongTags(doc.ExtensionProps, opts.Tags); err != nil { return nil, err } logbasics.Info("tags after parsing x-kong-tags", "tags", kongTags) @@ -1086,7 +1086,13 @@ func Convert(content []byte, opts O2kOptions) (map[string]interface{}, error) { } route["name"] = operationBaseName route["methods"] = []string{method} - route["tags"] = kongTags + + kongRouteTags, err := getKongTags(operation.ExtensionProps, nil) + if err != nil { + return nil, err + } + route["tags"] = append(kongTags, kongRouteTags...) + if _, found := route["regex_priority"]; !found { route["regex_priority"] = regexPriority } else { diff --git a/openapi2kong/openapi2kong_test.go b/openapi2kong/openapi2kong_test.go index da30bb8..9ed463d 100644 --- a/openapi2kong/openapi2kong_test.go +++ b/openapi2kong/openapi2kong_test.go @@ -41,8 +41,15 @@ func Test_Openapi2kong(t *testing.T) { fileNameOut := strings.TrimSuffix(fileNameIn, ".yaml") + ".generated.json" // log.Printf("input file: '%v', expected file: '%v'", fileNameIn, fileNameExpected) dataIn, _ := os.ReadFile(fixturePath + fileNameIn) + + // for x-kong-tags tests + var tags []string + if !strings.Contains(string(dataIn), "x-kong-tags:") { + tags = []string{"OAS3_import", "OAS3file_" + fileNameIn} + } + dataOut, err := Convert(dataIn, O2kOptions{ - Tags: []string{"OAS3_import", "OAS3file_" + fileNameIn}, + Tags: tags, OIDC: true, }) if err != nil {