From 4d0742a2401e4fe791a4bc509f42b7f4cc8fa8db Mon Sep 17 00:00:00 2001 From: CrowleyRajapakse Date: Mon, 19 Feb 2024 15:05:29 +0530 Subject: [PATCH] adding graphql API creation --- .../internal/k8sClient/k8s_client.go | 22 +++++++++++++++++++ apim-apk-agent/internal/mapper/cr_mapper.go | 4 ++++ apim-apk-agent/internal/utils/apis_fetcher.go | 2 +- apim-apk-agent/pkg/transformer/api_model.go | 2 +- .../pkg/transformer/k8s_artifacts.go | 1 + apim-apk-agent/pkg/transformer/transformer.go | 17 +++++++++++--- apim-apk-agent/pkg/transformer/utils.go | 17 +++++++++++--- 7 files changed, 57 insertions(+), 8 deletions(-) diff --git a/apim-apk-agent/internal/k8sClient/k8s_client.go b/apim-apk-agent/internal/k8sClient/k8s_client.go index eba201e7..8309439b 100644 --- a/apim-apk-agent/internal/k8sClient/k8s_client.go +++ b/apim-apk-agent/internal/k8sClient/k8s_client.go @@ -134,6 +134,28 @@ func DeployHTTPRouteCR(httpRoute *gwapiv1b1.HTTPRoute, k8sClient client.Client) } } +// DeployGQLRouteCR applies the given GqlRoute struct to the Kubernetes cluster. +func DeployGQLRouteCR(gqlRoute *dpv1alpha2.GQLRoute, k8sClient client.Client) { + crGQLRoute := &dpv1alpha2.GQLRoute{} + if err := k8sClient.Get(context.Background(), client.ObjectKey{Namespace: gqlRoute.ObjectMeta.Namespace, Name: gqlRoute.Name}, crGQLRoute); err != nil { + if !k8error.IsNotFound(err) { + loggers.LoggerXds.Error("Unable to get GQLRoute CR: " + err.Error()) + } + if err := k8sClient.Create(context.Background(), gqlRoute); err != nil { + loggers.LoggerXds.Error("Unable to create GQLRoute CR: " + err.Error()) + } else { + loggers.LoggerXds.Info("GQLRoute CR created: " + gqlRoute.Name) + } + } else { + crGQLRoute.Spec = gqlRoute.Spec + if err := k8sClient.Update(context.Background(), crGQLRoute); err != nil { + loggers.LoggerXds.Error("Unable to update GQLRoute CR: " + err.Error()) + } else { + loggers.LoggerXds.Info("GQLRoute CR updated: " + gqlRoute.Name) + } + } +} + // DeploySecretCR applies the given Secret struct to the Kubernetes cluster. func DeploySecretCR(secret *corev1.Secret, k8sClient client.Client) { crSecret := &corev1.Secret{} diff --git a/apim-apk-agent/internal/mapper/cr_mapper.go b/apim-apk-agent/internal/mapper/cr_mapper.go index 2486bee0..f2eda92c 100644 --- a/apim-apk-agent/internal/mapper/cr_mapper.go +++ b/apim-apk-agent/internal/mapper/cr_mapper.go @@ -48,6 +48,10 @@ func MapAndCreateCR(k8sArtifact transformer.K8sArtifacts, k8sClient client.Clien httpRoutes.Namespace = namespace internalk8sClient.DeployHTTPRouteCR(httpRoutes, k8sClient) } + for _, gqlRoutes := range k8sArtifact.GQLRoutes { + gqlRoutes.Namespace = namespace + internalk8sClient.DeployGQLRouteCR(gqlRoutes, k8sClient) + } for _, backends := range k8sArtifact.Backends { backends.Namespace = namespace internalk8sClient.DeployBackendCR(backends, k8sClient) diff --git a/apim-apk-agent/internal/utils/apis_fetcher.go b/apim-apk-agent/internal/utils/apis_fetcher.go index ec1e4a3e..37a197d0 100644 --- a/apim-apk-agent/internal/utils/apis_fetcher.go +++ b/apim-apk-agent/internal/utils/apis_fetcher.go @@ -114,7 +114,7 @@ func FetchAPIsOnEvent(conf *config.Config, apiUUID *string, k8sClient client.Cli return nil, err } k8ResourceEndpoint := conf.DataPlane.K8ResourceEndpoint - crResponse, err := transformer.GenerateCRs(apkConf, artifact.Swagger, k8ResourceEndpoint) + crResponse, err := transformer.GenerateCRs(apkConf, artifact.Schema, k8ResourceEndpoint) if err != nil { logger.LoggerSync.Errorf("Error occured in receiving the updated CRDs: %v", err) return nil, err diff --git a/apim-apk-agent/pkg/transformer/api_model.go b/apim-apk-agent/pkg/transformer/api_model.go index 9a0235d2..a6d2a3ef 100644 --- a/apim-apk-agent/pkg/transformer/api_model.go +++ b/apim-apk-agent/pkg/transformer/api_model.go @@ -111,7 +111,7 @@ type APIArtifact struct { APIJson string `json:"apiJson"` APIFileName string `json:"apiFileName"` EnvConfig string `json:"envConfig"` - Swagger string `json:"swagger"` + Schema string `json:"schema"` DeploymentDescriptor string `json:"deploymentDescriptor"` ClientCerts string `json:"clientCert"` RevisionID uint32 `json:"revisionId"` diff --git a/apim-apk-agent/pkg/transformer/k8s_artifacts.go b/apim-apk-agent/pkg/transformer/k8s_artifacts.go index 39f9c24f..7cfe4d5b 100644 --- a/apim-apk-agent/pkg/transformer/k8s_artifacts.go +++ b/apim-apk-agent/pkg/transformer/k8s_artifacts.go @@ -11,6 +11,7 @@ import ( type K8sArtifacts struct { API dpv1alpha2.API HTTPRoutes map[string]*gwapiv1b1.HTTPRoute + GQLRoutes map[string]*dpv1alpha2.GQLRoute Backends map[string]*v1alpha1.Backend Scopes map[string]*v1alpha1.Scope Authentication map[string]*dpv1alpha2.Authentication diff --git a/apim-apk-agent/pkg/transformer/transformer.go b/apim-apk-agent/pkg/transformer/transformer.go index 98a0f0d5..04d73316 100644 --- a/apim-apk-agent/pkg/transformer/transformer.go +++ b/apim-apk-agent/pkg/transformer/transformer.go @@ -150,8 +150,8 @@ func getAPIType(protocolType string) string { switch protocolType { case "HTTP", "HTTPS": apiType = "REST" - case "GraphQL": - apiType = "GraphQL" + case "GRAPHQL": + apiType = "GRAPHQL" } return apiType } @@ -238,7 +238,7 @@ func mapAuthConfigs(authHeader string, secSchemes []string, certAvailable bool, // GenerateCRs takes the .apk-conf, api definition, vHost and the organization for a particular API and then generate and returns // the relavant CRD set as a zip func GenerateCRs(apkConf string, apiDefinition string, k8ResourceGenEndpoint string) (*K8sArtifacts, error) { - k8sArtifact := K8sArtifacts{HTTPRoutes: make(map[string]*gwapiv1b1.HTTPRoute), Backends: make(map[string]*dpv1alpha1.Backend), Scopes: make(map[string]*dpv1alpha1.Scope), Authentication: make(map[string]*dpv1alpha2.Authentication), APIPolicies: make(map[string]*dpv1alpha2.APIPolicy), InterceptorServices: make(map[string]*dpv1alpha1.InterceptorService), ConfigMaps: make(map[string]*corev1.ConfigMap), Secrets: make(map[string]*corev1.Secret), RateLimitPolicies: make(map[string]*dpv1alpha1.RateLimitPolicy)} + k8sArtifact := K8sArtifacts{HTTPRoutes: make(map[string]*gwapiv1b1.HTTPRoute), GQLRoutes: make(map[string]*dpv1alpha2.GQLRoute), Backends: make(map[string]*dpv1alpha1.Backend), Scopes: make(map[string]*dpv1alpha1.Scope), Authentication: make(map[string]*dpv1alpha2.Authentication), APIPolicies: make(map[string]*dpv1alpha2.APIPolicy), InterceptorServices: make(map[string]*dpv1alpha1.InterceptorService), ConfigMaps: make(map[string]*corev1.ConfigMap), Secrets: make(map[string]*corev1.Secret), RateLimitPolicies: make(map[string]*dpv1alpha1.RateLimitPolicy)} if apkConf == "" { logger.LoggerTransformer.Error("Empty apk-conf parameter provided. Unable to generate CRDs.") return nil, errors.New("Error: APK-Conf can't be empty") @@ -429,6 +429,14 @@ func GenerateCRs(apkConf string, apiDefinition string, k8ResourceGenEndpoint str continue } k8sArtifact.Secrets[secret.Name] = &secret + case "GQLRoute": + var gqlRoute dpv1alpha2.GQLRoute + err = k8Yaml.Unmarshal(yamlData, &gqlRoute) + if err != nil { + logger.LoggerSync.Errorf("Error unmarshaling GQLRoute YAML: %v", err) + continue + } + k8sArtifact.GQLRoutes[gqlRoute.Name] = &gqlRoute default: logger.LoggerSync.Errorf("[!]Unknown Kind parsed from the YAML File: %v", kind) } @@ -523,6 +531,9 @@ func addOrganization(k8sArtifact *K8sArtifacts, organization string) { for _, httproutes := range k8sArtifact.HTTPRoutes { httproutes.ObjectMeta.Labels[k8sOrganizationField] = organizationHash } + for _, gqlroutes := range k8sArtifact.GQLRoutes { + gqlroutes.ObjectMeta.Labels[k8sOrganizationField] = organizationHash + } for _, authentication := range k8sArtifact.Authentication { authentication.ObjectMeta.Labels[k8sOrganizationField] = organizationHash } diff --git a/apim-apk-agent/pkg/transformer/utils.go b/apim-apk-agent/pkg/transformer/utils.go index fb8d5a34..e57611ee 100644 --- a/apim-apk-agent/pkg/transformer/utils.go +++ b/apim-apk-agent/pkg/transformer/utils.go @@ -78,7 +78,15 @@ func readZipFile(file *zip.File) (*APIArtifact, error) { if err != nil { return nil, err } - apiArtifact.Swagger = string(openAPIContent) + apiArtifact.Schema = string(openAPIContent) + } + + if strings.Contains(file.Name, "schema.graphql") { + graphqlContent, err := ReadContent(file) + if err != nil { + return nil, err + } + apiArtifact.Schema = string(graphqlContent) } if strings.Contains(file.Name, "api.json") { @@ -118,8 +126,11 @@ func readAPIZipFile(file *zip.File, apiArtifact *APIArtifact) error { } if strings.Contains(file.Name, "swagger.json") { - apiArtifact.Swagger = string(content) + apiArtifact.Schema = string(content) + } + if strings.Contains(file.Name, "schema.graphql") { + apiArtifact.Schema = string(content) } if strings.Contains(file.Name, "api.json") { @@ -215,7 +226,7 @@ func DecodeAPIArtifacts(payload []byte) ([]APIArtifact, error) { apiArtifacts = append(apiArtifacts, apiArtifact) } apiArtifact.APIJson = "" - apiArtifact.Swagger = "" + apiArtifact.Schema = "" apiArtifact.RevisionID = 0 apiArtifact.APIFileName = "" }