From e6c590300269ebf90fd9d6a76ea88d40527ed22a Mon Sep 17 00:00:00 2001 From: Tharsanan1 Date: Sun, 29 Sep 2024 15:35:20 +0530 Subject: [PATCH] Delete AiRatelimit policies when api ratelimits disabled --- .../internal/k8sClient/k8s_client.go | 28 +++++++++++++++++++ apim-apk-agent/internal/utils/apis_fetcher.go | 22 ++++++++++++++- apim-apk-agent/pkg/transformer/transformer.go | 12 ++++---- .../pkg/transformer/transformer_test.go | 4 +-- 4 files changed, 57 insertions(+), 9 deletions(-) diff --git a/apim-apk-agent/internal/k8sClient/k8s_client.go b/apim-apk-agent/internal/k8sClient/k8s_client.go index 467b11b2..12ff2656 100644 --- a/apim-apk-agent/internal/k8sClient/k8s_client.go +++ b/apim-apk-agent/internal/k8sClient/k8s_client.go @@ -344,6 +344,34 @@ func DeleteAIProviderCR(aiProviderName string, k8sClient client.Client) { } } +// DeleteAIRatelimitPolicy removes the AIRatelimitPolicy Custom Resource from the Kubernetes cluster based on CR name +func DeleteAIRatelimitPolicy(airlName string, k8sClient client.Client) { + conf, errReadConfig := config.ReadConfigs() + if errReadConfig != nil { + loggers.LoggerK8sClient.Errorf("Error reading configurations: %v", errReadConfig) + return + } + + crAIRatelimitPolicy := &dpv1alpha3.AIRateLimitPolicy{} + err := k8sClient.Get(context.Background(), client.ObjectKey{Namespace: conf.DataPlane.Namespace, Name: airlName}, crAIRatelimitPolicy) + if err != nil { + if k8error.IsNotFound(err) { + loggers.LoggerK8sClient.Infof("AIRatelimitPolicy CR not found: %s", airlName) + } else { + loggers.LoggerK8sClient.Error("Unable to get AIRatelimitPolicy CR: " + err.Error()) + } + return + } + + // Proceed to delete the CR if it was successfully retrieved + err = k8sClient.Delete(context.Background(), crAIRatelimitPolicy, &client.DeleteOptions{}) + if err != nil { + loggers.LoggerK8sClient.Errorf("Unable to delete AIRatelimitPolicy CR: %v", err) + } else { + loggers.LoggerK8sClient.Infof("Deleted AIRatelimitPolicy CR: %s Successfully", airlName) + } +} + // DeployRateLimitPolicyCR applies the given RateLimitPolicies struct to the Kubernetes cluster. func DeployRateLimitPolicyCR(rateLimitPolicies *dpv1alpha1.RateLimitPolicy, k8sClient client.Client) { crRateLimitPolicies := &dpv1alpha1.RateLimitPolicy{} diff --git a/apim-apk-agent/internal/utils/apis_fetcher.go b/apim-apk-agent/internal/utils/apis_fetcher.go index 60f29694..933d5ba2 100644 --- a/apim-apk-agent/internal/utils/apis_fetcher.go +++ b/apim-apk-agent/internal/utils/apis_fetcher.go @@ -25,6 +25,8 @@ package synchronizer import ( "fmt" + "crypto/sha1" + "encoding/hex" "archive/zip" "bytes" @@ -38,6 +40,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" mapperUtil "github.com/wso2/product-apim-tooling/apim-apk-agent/internal/mapper" + k8sclientUtil "github.com/wso2/product-apim-tooling/apim-apk-agent/internal/k8sClient" ) func init() { @@ -108,7 +111,15 @@ func FetchAPIsOnEvent(conf *config.Config, apiUUID *string, k8sClient client.Cli return nil, err } - apkConf, apiUUID, revisionID, configuredRateLimitPoliciesMap, endpointSecurityData, apkErr := transformer.GenerateAPKConf(artifact.APIJson, artifact.CertArtifact, apiDeployment.OrganizationID) + apkConf, apiUUID, revisionID, configuredRateLimitPoliciesMap, endpointSecurityData, api, prodAIRL, sandAIRL, apkErr := transformer.GenerateAPKConf(artifact.APIJson, artifact.CertArtifact, apiDeployment.OrganizationID) + if prodAIRL == nil { + // Try to delete production AI ratelimit for this api + k8sclientUtil.DeleteAIRatelimitPolicy(generateSHA1HexHash(api.Name, api.Version, "production"), k8sClient) + } + if sandAIRL == nil { + // Try to delete production AI ratelimit for this api + k8sclientUtil.DeleteAIRatelimitPolicy(generateSHA1HexHash(api.Name, api.Version, "sandbox"), k8sClient) + } if apkErr != nil { logger.LoggerUtils.Errorf("Error while generating APK-Conf: %v", apkErr) return nil, err @@ -162,6 +173,15 @@ func FetchAPIsOnEvent(conf *config.Config, apiUUID *string, k8sClient client.Cli return nil, nil } +// generateSHA1HexHash hashes the concatenated strings and returns the SHA-1 hash in base16 (hex) encoding. +func generateSHA1HexHash(name, version, env string) string { + data := name + version + env + hasher := sha1.New() + hasher.Write([]byte(data)) + hashBytes := hasher.Sum(nil) + return hex.EncodeToString(hashBytes) +} + // GetAPI function calls the FetchAPIs() with relevant environment labels defined in the config. func GetAPI(c chan sync.SyncAPIResponse, id *string, envs []string, endpoint string, sendType bool) { if len(envs) > 0 { diff --git a/apim-apk-agent/pkg/transformer/transformer.go b/apim-apk-agent/pkg/transformer/transformer.go index f9b45760..00189073 100644 --- a/apim-apk-agent/pkg/transformer/transformer.go +++ b/apim-apk-agent/pkg/transformer/transformer.go @@ -57,7 +57,7 @@ import ( ) // GenerateAPKConf will Generate the mapped .apk-conf file for a given API Project zip -func GenerateAPKConf(APIJson string, certArtifact CertificateArtifact, organizationID string) (string, string, uint32, map[string]eventHub.RateLimitPolicy, EndpointSecurityConfig, error) { +func GenerateAPKConf(APIJson string, certArtifact CertificateArtifact, organizationID string) (string, string, uint32, map[string]eventHub.RateLimitPolicy, EndpointSecurityConfig, *API, *AIRatelimit, *AIRatelimit, error) { apk := &API{} @@ -71,7 +71,7 @@ func GenerateAPKConf(APIJson string, certArtifact CertificateArtifact, organizat if apiYamlError != nil { logger.LoggerTransformer.Error("Error while unmarshalling api.json content", apiYamlError) - return "", "null", 0, nil, EndpointSecurityConfig{}, apiYamlError + return "", "null", 0, nil, EndpointSecurityConfig{}, nil, nil, nil, apiYamlError } apiYamlData := apiYaml.Data @@ -167,7 +167,7 @@ func GenerateAPKConf(APIJson string, certArtifact CertificateArtifact, organizat certErr := json.Unmarshal([]byte(certArtifact.EndpointCerts), &endpointCertList) if certErr != nil { logger.LoggerTransformer.Errorf("Error while unmarshalling endpoint_cert.json content: %v", apiYamlError) - return "", "null", 0, nil, EndpointSecurityConfig{}, certErr + return "", "null", 0, nil, EndpointSecurityConfig{}, nil, nil, nil, certErr } endCertAvailable = true } @@ -190,7 +190,7 @@ func GenerateAPKConf(APIJson string, certArtifact CertificateArtifact, organizat certErr := json.Unmarshal([]byte(certArtifact.ClientCerts), &certList) if certErr != nil { logger.LoggerTransformer.Errorf("Error while unmarshalling client_cert.json content: %v", apiYamlError) - return "", "null", 0, nil, EndpointSecurityConfig{}, certErr + return "", "null", 0, nil, EndpointSecurityConfig{}, nil, nil, nil, certErr } certAvailable = true } @@ -222,9 +222,9 @@ func GenerateAPKConf(APIJson string, certArtifact CertificateArtifact, organizat if marshalError != nil { logger.LoggerTransformer.Error("Error while marshalling apk yaml", marshalError) - return "", "null", 0, nil, EndpointSecurityConfig{}, marshalError + return "", "null", 0, nil, EndpointSecurityConfig{}, nil, prodAIRatelimit, sandAIRatelimit, marshalError } - return string(c), apiYamlData.RevisionedAPIID, apiYamlData.RevisionID, configuredRateLimitPoliciesMap, endpointSecurityData, nil + return string(c), apiYamlData.RevisionedAPIID, apiYamlData.RevisionID, configuredRateLimitPoliciesMap, endpointSecurityData, apk, prodAIRatelimit, sandAIRatelimit, nil } // prepareAIRatelimit Function that accepts apiYamlData and returns AIRatelimit diff --git a/apim-apk-agent/pkg/transformer/transformer_test.go b/apim-apk-agent/pkg/transformer/transformer_test.go index 04b2b311..2a9c1113 100644 --- a/apim-apk-agent/pkg/transformer/transformer_test.go +++ b/apim-apk-agent/pkg/transformer/transformer_test.go @@ -145,7 +145,7 @@ func TestAPKConfGeneration(t *testing.T) { assert.NoError(t, err) assert.IsType(t, &APIArtifact{}, apiArtifact) - apkConf, apiUUID, revisionID, configuredRateLimitPoliciesMap, endpointSecurityData, apkErr := GenerateAPKConf(apiArtifact.APIJson, apiArtifact.CertArtifact, "default") + apkConf, apiUUID, revisionID, configuredRateLimitPoliciesMap, endpointSecurityData, _, _, _, apkErr := GenerateAPKConf(apiArtifact.APIJson, apiArtifact.CertArtifact, "default") assert.NoError(t, apkErr) assert.NotEmpty(t, apkConf) @@ -359,7 +359,7 @@ func TestBrokenZipHandlingFlow(t *testing.T) { assert.Error(t, err) } - apkConf, apiUUID, revisionID, configuredRateLimitPoliciesMap, endpointSecurityData, apkErr := GenerateAPKConf(apiArtifact.APIJson, apiArtifact.CertArtifact, "orgID") + apkConf, apiUUID, revisionID, configuredRateLimitPoliciesMap, endpointSecurityData, _, _, _, apkErr := GenerateAPKConf(apiArtifact.APIJson, apiArtifact.CertArtifact, "orgID") //When all the contents are empty or some properties are missing, an unmarshalling error should occur when creating the apiArtifact if strings.Contains(zipFile.Name, "All_Empty") {