From a37b7b9dee9de6ad6126cdf45c08d5a0ff5c8b25 Mon Sep 17 00:00:00 2001 From: sgayangi Date: Fri, 9 Feb 2024 13:08:16 +0530 Subject: [PATCH] Update configds for subscription type --- .../ballerina/APIClient.bal | 28 ++++++--- .../ballerina/modules/model/GraphQLRoute.bal | 21 +++++-- .../generated_graphql_conf.apk-conf} | 0 .../graphql/graphql_conf_with_sub.apk-conf | 59 +++++++++++++++++++ .../graphql/graphql_conf_without_sub.apk-conf | 55 +++++++++++++++++ .../test/resources/tests/api/GraphQL.feature | 17 +++++- 6 files changed, 167 insertions(+), 13 deletions(-) rename test/cucumber-tests/src/test/resources/artifacts/apk-confs/{graphql_conf.apk-conf => graphql/generated_graphql_conf.apk-conf} (100%) create mode 100644 test/cucumber-tests/src/test/resources/artifacts/apk-confs/graphql/graphql_conf_with_sub.apk-conf create mode 100644 test/cucumber-tests/src/test/resources/artifacts/apk-confs/graphql/graphql_conf_without_sub.apk-conf diff --git a/runtime/config-deployer-service/ballerina/APIClient.bal b/runtime/config-deployer-service/ballerina/APIClient.bal index 6631b0ca4..1910545d3 100644 --- a/runtime/config-deployer-service/ballerina/APIClient.bal +++ b/runtime/config-deployer-service/ballerina/APIClient.bal @@ -757,8 +757,13 @@ public class APIClient { } if endpointToUse != () { if apkConf.'type == API_TYPE_GRAPHQL { - model:GQLRouteRule gqlRouteRule = {matches: self.retrieveGQLMatches(apkConf, operation, organization)}; - return gqlRouteRule; + model:GQLRouteMatch[]|error routeMatches = self.retrieveGQLMatches(apkConf, operation, organization); + if routeMatches is model:GQLRouteMatch[] && routeMatches.length() > 0 { + model:GQLRouteRule gqlRouteRule = {matches: routeMatches}; + return gqlRouteRule; + } else { + return e909022("Subscription type currently not supported for GraphQL APIs.", error("Subscription type currently not supported for GraphQL APIs.")); + } } else { model:HTTPRouteRule httpRouteRule = {matches: self.retrieveHTTPMatches(apkConf, operation, organization), backendRefs: self.retrieveGeneratedBackend(apkConf, endpointToUse, endpointType), filters: self.generateFilters(apiArtifact, apkConf, endpointToUse, operation, endpointType, organization)}; return httpRouteRule; @@ -895,19 +900,28 @@ public class APIClient { return httpRouteMatch; } - private isolated function retrieveGQLMatches(APKConf apkConf, APKOperations apiOperation, commons:Organization organization) returns model:GQLRouteMatch[] { + private isolated function retrieveGQLMatches(APKConf apkConf, APKOperations apiOperation, commons:Organization organization) returns model:GQLRouteMatch[]|error { model:GQLRouteMatch[] gqlRouteMatch = []; - model:GQLRouteMatch gqlRoute = self.retrieveGQLRouteMatch(apiOperation); - gqlRouteMatch.push(gqlRoute); + model:GQLRouteMatch|error gqlRoute = self.retrieveGQLRouteMatch(apiOperation); + if gqlRoute is model:GQLRouteMatch { + gqlRouteMatch.push(gqlRoute); + } return gqlRouteMatch; + } private isolated function retrieveHttpRouteMatch(APKConf apkConf, APKOperations apiOperation, commons:Organization organization) returns model:HTTPRouteMatch { return {method: apiOperation.verb, path: {'type: "RegularExpression", value: self.retrievePathPrefix(apkConf.basePath, apkConf.'version, apiOperation.target ?: "/*", organization)}}; } - private isolated function retrieveGQLRouteMatch(APKOperations apiOperation) returns model:GQLRouteMatch { - return {'type: apiOperation.verb, path: apiOperation.target}; + private isolated function retrieveGQLRouteMatch(APKOperations apiOperation) returns model:GQLRouteMatch|error { + model:GQLType? routeMatch = model:getGQLRouteMatch(apiOperation.verb); + if routeMatch is model:GQLType { + log:printInfo(routeMatch); + return {'type: routeMatch, path: apiOperation.target}; + } else { + return e909052(error("Error occured retrieving GQL route match", message = "Internal Server Error", code = 909000, description = "Internal Server Error", statusCode = 500)); + } } isolated function retrieveGeneratedSwaggerDefinition(APKConf apkConf, string? definition) returns string|json|commons:APKError|error { diff --git a/runtime/config-deployer-service/ballerina/modules/model/GraphQLRoute.bal b/runtime/config-deployer-service/ballerina/modules/model/GraphQLRoute.bal index e74c1075b..e471cefac 100644 --- a/runtime/config-deployer-service/ballerina/modules/model/GraphQLRoute.bal +++ b/runtime/config-deployer-service/ballerina/modules/model/GraphQLRoute.bal @@ -30,14 +30,25 @@ public type GQLRouteList record {| |}; public type GQLRouteMatch record { - string 'type; //TODO: make enum + GQLType 'type; string path; }; -enum GQLType { - QUERY, - MUTATION -}; +public type GQLType "QUERY"|"MUTATION"; + +public isolated function getGQLRouteMatch(string routeMatch) returns GQLType? { + match routeMatch { + "QUERY" => { + return "QUERY"; + } + "MUTATION" => { + return "MUTATION"; + } //TODO: add SUBSCRIPTION when support is added + _ => { + return; // Returns `nil` for unmatched cases + } + } +} public type GQLRouteFilter record { LocalObjectReference extensionRef?; diff --git a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/graphql_conf.apk-conf b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/graphql/generated_graphql_conf.apk-conf similarity index 100% rename from test/cucumber-tests/src/test/resources/artifacts/apk-confs/graphql_conf.apk-conf rename to test/cucumber-tests/src/test/resources/artifacts/apk-confs/graphql/generated_graphql_conf.apk-conf diff --git a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/graphql/graphql_conf_with_sub.apk-conf b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/graphql/graphql_conf_with_sub.apk-conf new file mode 100644 index 000000000..11e102205 --- /dev/null +++ b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/graphql/graphql_conf_with_sub.apk-conf @@ -0,0 +1,59 @@ +--- +name: "GraphQL API" +basePath: "/graphql" +version: "3.14" +type: "GRAPHQL" +defaultVersion: false +subscriptionValidation: false +endpointConfigurations: + production: + endpoint: "https://run.mocky.io/v3/85516819-1edd-412b-a32b-a9284705a0b4" +operations: + - target: "hero" + verb: "QUERY" + secured: true + scopes: [] + - target: "reviews" + verb: "QUERY" + secured: true + scopes: [] + - target: "search" + verb: "QUERY" + secured: true + scopes: [] + - target: "character" + verb: "QUERY" + secured: true + scopes: [] + - target: "droid" + verb: "QUERY" + secured: true + scopes: [] + - target: "human" + verb: "QUERY" + secured: true + scopes: [] + - target: "allHumans" + verb: "QUERY" + secured: true + scopes: [] + - target: "allDroids" + verb: "QUERY" + secured: true + scopes: [] + - target: "allCharacters" + verb: "QUERY" + secured: true + scopes: [] + - target: "starship" + verb: "QUERY" + secured: true + scopes: [] + - target: "createReview" + verb: "MUTATION" + secured: true + scopes: [] + - target: "reviewAdded" + verb: "SUBSCRIPTION" + secured: true + scopes: [] diff --git a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/graphql/graphql_conf_without_sub.apk-conf b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/graphql/graphql_conf_without_sub.apk-conf new file mode 100644 index 000000000..fcbefb327 --- /dev/null +++ b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/graphql/graphql_conf_without_sub.apk-conf @@ -0,0 +1,55 @@ +--- +name: "GraphQL API" +basePath: "/graphql" +version: "3.14" +type: "GRAPHQL" +defaultVersion: false +subscriptionValidation: false +endpointConfigurations: + production: + endpoint: "https://run.mocky.io/v3/85516819-1edd-412b-a32b-a9284705a0b4" +operations: + - target: "hero" + verb: "QUERY" + secured: true + scopes: [] + - target: "reviews" + verb: "QUERY" + secured: true + scopes: [] + - target: "search" + verb: "QUERY" + secured: true + scopes: [] + - target: "character" + verb: "QUERY" + secured: true + scopes: [] + - target: "droid" + verb: "QUERY" + secured: true + scopes: [] + - target: "human" + verb: "QUERY" + secured: true + scopes: [] + - target: "allHumans" + verb: "QUERY" + secured: true + scopes: [] + - target: "allDroids" + verb: "QUERY" + secured: true + scopes: [] + - target: "allCharacters" + verb: "QUERY" + secured: true + scopes: [] + - target: "starship" + verb: "QUERY" + secured: true + scopes: [] + - target: "createReview" + verb: "MUTATION" + secured: true + scopes: [] diff --git a/test/cucumber-tests/src/test/resources/tests/api/GraphQL.feature b/test/cucumber-tests/src/test/resources/tests/api/GraphQL.feature index e1930538d..1e068f0c7 100644 --- a/test/cucumber-tests/src/test/resources/tests/api/GraphQL.feature +++ b/test/cucumber-tests/src/test/resources/tests/api/GraphQL.feature @@ -4,7 +4,22 @@ Feature: Generating APK conf for GraphQL API When I use the definition file "artifacts/definitions/graphql_sample_api.graphql" in resources And generate the APK conf file for a "GRAPHQL" API Then the response status code should be 200 - And the response body should be "artifacts/apk-confs/graphql_conf.apk-conf" in resources + + Scenario: Deploying APK conf using a valid GraphQL API definition without a subscription resource + Given The system is ready + And I have a valid subscription + When I use the APK Conf file "artifacts/apk-confs/graphql/graphql_conf_without_sub.apk-conf" + And the definition file "artifacts/definitions/graphql_sample_api.graphql" + And make the API deployment request + Then the response status code should be 200 + + Scenario: Deploying APK conf using a valid GraphQL API definition containing a subscription resource + Given The system is ready + And I have a valid subscription + When I use the APK Conf file "artifacts/apk-confs/graphql/graphql_conf_with_sub.apk-conf" + And the definition file "artifacts/definitions/graphql_sample_api.graphql" + And make the API deployment request + Then the response status code should be 500 Scenario: Generating APK conf using an invalid GraphQL API definition Given The system is ready