From f21071a34f9c7e737499fa3083eb741f6bbf6c4e Mon Sep 17 00:00:00 2001 From: Aditya Thebe Date: Wed, 3 Apr 2024 18:08:45 +0545 Subject: [PATCH] feat: delete static resources when the canary is deleted --- checks/kubernetes_resource.go | 9 ++-- ....yaml => kubernetes_resource_ingress.yaml} | 16 +++---- fixtures/k8s/kubernetes_resource_service.yaml | 43 +++++++++++++++++++ fixtures/k8s/kustomization.yaml | 3 +- pkg/db/canary.go | 27 +++++++++++- 5 files changed, 82 insertions(+), 16 deletions(-) rename fixtures/k8s/{kubernetes_resource.yaml => kubernetes_resource_ingress.yaml} (74%) create mode 100644 fixtures/k8s/kubernetes_resource_service.yaml diff --git a/checks/kubernetes_resource.go b/checks/kubernetes_resource.go index a3d0e34f0..248ee6773 100644 --- a/checks/kubernetes_resource.go +++ b/checks/kubernetes_resource.go @@ -11,6 +11,7 @@ import ( "github.com/flanksource/commons/duration" "github.com/flanksource/commons/logger" + "github.com/flanksource/commons/utils" "github.com/flanksource/duty/types" "github.com/flanksource/canary-checker/api/context" @@ -105,7 +106,7 @@ func (c *KubernetesResourceChecker) Check(ctx *context.Context, check v1.Kuberne // annotate the resource with the canary ID so we can easily clean it up later // TODO: see if this is actually needed resource.SetAnnotations(map[string]string{annotationkey: ctx.Canary.ID()}) - if err := ctx.Kommons().ApplyUnstructured(ctx.Namespace, &resource); err != nil { + if err := ctx.Kommons().ApplyUnstructured(utils.Coalesce(resource.GetNamespace(), ctx.Namespace), &resource); err != nil { return results.Failf("failed to apply static resource %s: %v", resource.GetName(), err) } } @@ -113,12 +114,12 @@ func (c *KubernetesResourceChecker) Check(ctx *context.Context, check v1.Kuberne for i := range check.Resources { resource := check.Resources[i] resource.SetAnnotations(map[string]string{annotationkey: ctx.Canary.ID()}) - if err := ctx.Kommons().ApplyUnstructured(ctx.Namespace, &resource); err != nil { + if err := ctx.Kommons().ApplyUnstructured(utils.Coalesce(resource.GetNamespace(), ctx.Namespace), &resource); err != nil { return results.Failf("failed to apply resource %s: %v", resource.GetName(), err) } defer func() { - if err := ctx.Kommons().DeleteUnstructured(ctx.Namespace, &resource); err != nil { + if err := ctx.Kommons().DeleteUnstructured(utils.Coalesce(resource.GetNamespace(), ctx.Namespace), &resource); err != nil { logger.Errorf("failed to delete resource %s: %v", resource.GetName(), err) results.ErrorMessage(fmt.Errorf("failed to delete resource %s: %v", resource.GetName(), err)) } @@ -172,7 +173,7 @@ func (c *KubernetesResourceChecker) Check(ctx *context.Context, check v1.Kuberne }, } if err := templater.Walk(&virtualCanary); err != nil { - return results.Failf("error templating checks %v", err) + return results.Failf("error templating checks: %v", err) } checkCtx := context.New(ctx.Context, virtualCanary) diff --git a/fixtures/k8s/kubernetes_resource.yaml b/fixtures/k8s/kubernetes_resource_ingress.yaml similarity index 74% rename from fixtures/k8s/kubernetes_resource.yaml rename to fixtures/k8s/kubernetes_resource_ingress.yaml index df1ee1115..aea3a045d 100644 --- a/fixtures/k8s/kubernetes_resource.yaml +++ b/fixtures/k8s/kubernetes_resource_ingress.yaml @@ -2,7 +2,7 @@ apiVersion: canaries.flanksource.com/v1 kind: Canary metadata: - name: nginx-pod-creation-tests + name: ingress-test namespace: default labels: "Expected-Fail": "false" @@ -22,7 +22,7 @@ spec: namespace: default spec: rules: - - host: 'httpbin.test.flanksource.com' + - host: "httpbin.test.flanksource.com" http: paths: - pathType: Prefix @@ -41,7 +41,7 @@ spec: spec: containers: - name: httpbin - image: 'kennethreitz/httpbin:latest' + image: "kennethreitz/httpbin:latest" ports: - containerPort: 80 - apiVersion: v1 @@ -57,12 +57,8 @@ spec: targetPort: 80 checks: - http: - - url: "http://ingress-nginx.ingress-nginx.svc" + - name: Call httpbin via ingress + url: "http://ingress-nginx.ingress-nginx.svc" headers: - name: Host - value: "nginx.test.flanksource.com" - # - url: "http://localhost:1337" - # headers: - # - name: host - # value: "httpbin.test.flanksource.com" - # # value: "{{(index (index .staticResources 0).spec.rules 0).host}}" + value: "{{(index ((index .staticResources 0).Object.spec.rules) 0).host}}" diff --git a/fixtures/k8s/kubernetes_resource_service.yaml b/fixtures/k8s/kubernetes_resource_service.yaml new file mode 100644 index 000000000..cd4edc19e --- /dev/null +++ b/fixtures/k8s/kubernetes_resource_service.yaml @@ -0,0 +1,43 @@ +--- +apiVersion: canaries.flanksource.com/v1 +kind: Canary +metadata: + name: pod-svc-test + namespace: default + labels: + "Expected-Fail": "false" +spec: + schedule: "@every 5m" + kubernetesResource: + - name: service accessibility test + namespace: default + description: "deploy httpbin & check that it's accessible via its service" + waitForReady: true + timeout: 10m + resources: + - apiVersion: v1 + kind: Pod + metadata: + name: httpbin-pod-1 + namespace: default + spec: + containers: + - name: httpbin + image: "kennethreitz/httpbin:latest" + ports: + - containerPort: 80 + - apiVersion: v1 + kind: Service + metadata: + name: httpbin-svc + namespace: default + spec: + selector: + name: httpbin-pod-1 + ports: + - port: 80 + targetPort: 80 + checks: + - http: + - name: Call httpbin service + url: "http://httpbin-svc.default.svc" diff --git a/fixtures/k8s/kustomization.yaml b/fixtures/k8s/kustomization.yaml index d757f301c..ada3cab64 100644 --- a/fixtures/k8s/kustomization.yaml +++ b/fixtures/k8s/kustomization.yaml @@ -9,4 +9,5 @@ resources: - pod_fail.yaml - pod_pass.yaml - kubernetes_bundle.yaml - - kuberenetes_resource.yaml + - kubernetes_resource_ingress.yaml + - kubernetes_resource_service.yaml diff --git a/pkg/db/canary.go b/pkg/db/canary.go index cde1a1bb7..06f1a5c6c 100644 --- a/pkg/db/canary.go +++ b/pkg/db/canary.go @@ -208,6 +208,29 @@ func RemoveTransformedChecks(ctx context.Context, ids []string) error { Error } +func deleteStaticKubernetesResources(ctx context.Context, id string) error { + var canary models.Canary + if err := ctx.DB().Where("id = ?", id).First(&canary).Error; err != nil { + return err + } + + var spec v1.CanarySpec + if err := json.Unmarshal(canary.Spec, &spec); err != nil { + return err + } + + for _, kr := range spec.KubernetesResource { + for _, sr := range kr.StaticResources { + ctx.Infof("Deleting static resource (kind=%s, namespace=%s, name=%s)", sr.GetKind(), sr.GetNamespace(), sr.GetName()) + if err := ctx.Kommons().DeleteUnstructured(ctx.GetNamespace(), &sr); err != nil { + logger.Errorf("error deleting static resource (kind=%s, namespace=%s, name=%s): %v", sr.GetKind(), ctx.GetNamespace(), sr.GetName(), err) + } + } + } + + return nil +} + func DeleteCanary(ctx context.Context, id string) error { logger.Infof("Deleting canary[%s]", id) @@ -220,7 +243,9 @@ func DeleteCanary(ctx context.Context, id string) error { } metrics.UnregisterGauge(ctx, checkIDs) - // TODO: delete all the static resources + if err := deleteStaticKubernetesResources(ctx, id); err != nil { + return fmt.Errorf("failed to delete static kubernetes resources: %w", err) + } if err := DeleteCheckComponentRelationshipsForCanary(ctx.DB(), id); err != nil { return err