From c95ab684c64f7ec8b252f445e4e2f7e9f91d159f Mon Sep 17 00:00:00 2001 From: Austin Abro Date: Fri, 10 May 2024 19:49:57 +0000 Subject: [PATCH 01/12] fix adopt ns labels --- src/config/config.go | 1 - src/internal/packager/helm/post-render.go | 29 +++++++++++-------- src/pkg/cluster/common.go | 10 ++----- src/pkg/cluster/injector.go | 2 +- src/pkg/cluster/secrets.go | 9 +++--- src/pkg/cluster/state.go | 6 ++-- src/pkg/cluster/zarf.go | 7 +++-- src/pkg/k8s/common.go | 15 ++++++---- src/pkg/k8s/namespace.go | 25 ++++++++++++---- src/pkg/k8s/secrets.go | 2 +- src/pkg/k8s/types.go | 1 - src/pkg/packager/deploy.go | 2 +- src/test/e2e/25_helm_test.go | 7 +++++ .../25-manifest-adoption/deployment.yaml | 4 +++ 14 files changed, 74 insertions(+), 46 deletions(-) diff --git a/src/config/config.go b/src/config/config.go index 63396255b0..e7e9c47c21 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -34,7 +34,6 @@ const ( ZarfConnectAnnotationDescription = "zarf.dev/connect-description" ZarfConnectAnnotationURL = "zarf.dev/connect-url" - ZarfManagedByLabel = "app.kubernetes.io/managed-by" ZarfCleanupScriptsPath = "/opt/zarf" ZarfPackagePrefix = "zarf-package-" diff --git a/src/internal/packager/helm/post-render.go b/src/internal/packager/helm/post-render.go index 7cee486d99..b9adfef568 100644 --- a/src/internal/packager/helm/post-render.go +++ b/src/internal/packager/helm/post-render.go @@ -13,6 +13,7 @@ import ( "github.com/defenseunicorns/pkg/helpers" "github.com/defenseunicorns/zarf/src/config" + "github.com/defenseunicorns/zarf/src/pkg/k8s" "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/pkg/utils" "github.com/defenseunicorns/zarf/src/types" @@ -20,6 +21,7 @@ import ( corev1 "k8s.io/api/core/v1" "sigs.k8s.io/yaml" + "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" ) @@ -35,7 +37,16 @@ func (h *Helm) newRenderer() (*renderer, error) { namespaces := make(map[string]*corev1.Namespace) if h.cluster != nil { - namespaces[h.chart.Namespace] = h.cluster.NewZarfManagedNamespace(h.chart.Namespace) + namespace, err := h.cluster.K8s.GetNamespace(h.chart.Namespace) + if err != nil && !errors.IsNotFound(err) { + return nil, fmt.Errorf("unable to check for existing namespace %q in cluster: %s", h.chart.Namespace, err) + } + if h.cfg.DeployOpts.AdoptExistingResources && !errors.IsNotFound(err) { + namespaces[h.chart.Namespace] = k8s.UpdateNamespaceToBeZarfManaged(namespace) + } else { + namespaces[h.chart.Namespace] = k8s.NewZarfManagedNamespace(h.chart.Namespace) + } + } return &renderer{ @@ -167,22 +178,16 @@ func (r *renderer) editHelmResources(resources []releaseutil.Manifest, finalMani switch rawData.GetKind() { case "Namespace": - var namespace corev1.Namespace + namespace := new(corev1.Namespace) // parse the namespace resource so it can be applied out-of-band by zarf instead of helm to avoid helm ns shenanigans - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(rawData.UnstructuredContent(), &namespace); err != nil { + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(rawData.UnstructuredContent(), namespace); err != nil { message.WarnErrf(err, "could not parse namespace %s", rawData.GetName()) } else { message.Debugf("Matched helm namespace %s for zarf annotation", namespace.Name) - if namespace.Labels == nil { - // Ensure label map exists to avoid nil panic - namespace.Labels = make(map[string]string) - } - // Now track this namespace by zarf - namespace.Labels[config.ZarfManagedByLabel] = "zarf" - namespace.Labels["zarf-helm-release"] = r.chart.ReleaseName + namespace = k8s.UpdateNamespaceToBeZarfManaged(namespace) // Add it to the stack - r.namespaces[namespace.Name] = &namespace + r.namespaces[namespace.Name] = namespace } // skip so we can strip namespaces from helm's brain continue @@ -207,7 +212,7 @@ func (r *renderer) editHelmResources(resources []releaseutil.Manifest, finalMani namespace := rawData.GetNamespace() if _, exists := r.namespaces[namespace]; !exists && namespace != "" { // if this is the first time seeing this ns, we need to track that to create it as well - r.namespaces[namespace] = r.cluster.NewZarfManagedNamespace(namespace) + r.namespaces[namespace] = k8s.NewZarfManagedNamespace(namespace) } // If we have been asked to adopt existing resources, process those now as well diff --git a/src/pkg/cluster/common.go b/src/pkg/cluster/common.go index a84a06fee3..5650366945 100644 --- a/src/pkg/cluster/common.go +++ b/src/pkg/cluster/common.go @@ -7,7 +7,6 @@ package cluster import ( "time" - "github.com/defenseunicorns/zarf/src/config" "github.com/defenseunicorns/zarf/src/pkg/k8s" "github.com/defenseunicorns/zarf/src/pkg/message" ) @@ -20,13 +19,8 @@ type Cluster struct { const ( // DefaultTimeout is the default time to wait for a cluster to be ready. DefaultTimeout = 30 * time.Second - agentLabel = "zarf.dev/agent" ) -var labels = k8s.Labels{ - config.ZarfManagedByLabel: "zarf", -} - // NewClusterOrDie creates a new Cluster instance and waits up to 30 seconds for the cluster to be ready or throws a fatal error. func NewClusterOrDie() *Cluster { c, err := NewClusterWithWait(DefaultTimeout) @@ -45,7 +39,7 @@ func NewClusterWithWait(timeout time.Duration) (*Cluster, error) { c := &Cluster{} var err error - c.K8s, err = k8s.New(message.Debugf, labels) + c.K8s, err = k8s.New(message.Debugf) if err != nil { return nil, err } @@ -65,7 +59,7 @@ func NewCluster() (*Cluster, error) { c := &Cluster{} var err error - c.K8s, err = k8s.New(message.Debugf, labels) + c.K8s, err = k8s.New(message.Debugf) if err != nil { return nil, err } diff --git a/src/pkg/cluster/injector.go b/src/pkg/cluster/injector.go index 716a260b96..fb642203d9 100644 --- a/src/pkg/cluster/injector.go +++ b/src/pkg/cluster/injector.go @@ -321,7 +321,7 @@ func (c *Cluster) buildInjectionPod(node, image string, payloadConfigmaps []stri pod.Labels["app"] = "zarf-injector" // Ensure zarf agent doesn't break the injector on future runs - pod.Labels[agentLabel] = "ignore" + pod.Labels[k8s.ZarfManagedByLabel] = "ignore" // Bind the pod to the node the image was found on pod.Spec.NodeName = node diff --git a/src/pkg/cluster/secrets.go b/src/pkg/cluster/secrets.go index 2cdb1a20d1..2f77cad9de 100644 --- a/src/pkg/cluster/secrets.go +++ b/src/pkg/cluster/secrets.go @@ -12,6 +12,7 @@ import ( corev1 "k8s.io/api/core/v1" "github.com/defenseunicorns/zarf/src/config" + "github.com/defenseunicorns/zarf/src/pkg/k8s" "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/types" ) @@ -88,8 +89,8 @@ func (c *Cluster) UpdateZarfManagedImageSecrets(state *types.ZarfState) { } // Check if this is a Zarf managed secret or is in a namespace the Zarf agent will take action in - if currentRegistrySecret.Labels[config.ZarfManagedByLabel] == "zarf" || - (namespace.Labels[agentLabel] != "skip" && namespace.Labels[agentLabel] != "ignore") { + if currentRegistrySecret.Labels[k8s.ZarfManagedByLabel] == "zarf" || + (namespace.Labels[k8s.AgentLabel] != "skip" && namespace.Labels[k8s.AgentLabel] != "ignore") { spinner.Updatef("Updating existing Zarf-managed image secret for namespace: '%s'", namespace.Name) // Create the secret @@ -122,8 +123,8 @@ func (c *Cluster) UpdateZarfManagedGitSecrets(state *types.ZarfState) { } // Check if this is a Zarf managed secret or is in a namespace the Zarf agent will take action in - if currentGitSecret.Labels[config.ZarfManagedByLabel] == "zarf" || - (namespace.Labels[agentLabel] != "skip" && namespace.Labels[agentLabel] != "ignore") { + if currentGitSecret.Labels[k8s.ZarfManagedByLabel] == "zarf" || + (namespace.Labels[k8s.AgentLabel] != "skip" && namespace.Labels[k8s.AgentLabel] != "ignore") { spinner.Updatef("Updating existing Zarf-managed git secret for namespace: '%s'", namespace.Name) // Create the secret diff --git a/src/pkg/cluster/state.go b/src/pkg/cluster/state.go index ebac18fbd3..909851b50e 100644 --- a/src/pkg/cluster/state.go +++ b/src/pkg/cluster/state.go @@ -91,7 +91,7 @@ func (c *Cluster) InitZarfState(initOptions types.ZarfInitOptions) error { namespace.Labels = make(map[string]string) } // This label will tell the Zarf Agent to ignore this namespace. - namespace.Labels[agentLabel] = "ignore" + namespace.Labels[k8s.AgentLabel] = "ignore" namespaceCopy := namespace if _, err = c.UpdateNamespace(&namespaceCopy); err != nil { // This is not a hard failure, but we should log it. @@ -101,7 +101,7 @@ func (c *Cluster) InitZarfState(initOptions types.ZarfInitOptions) error { // Try to create the zarf namespace. spinner.Updatef("Creating the Zarf namespace") - zarfNamespace := c.NewZarfManagedNamespace(ZarfNamespaceName) + zarfNamespace := k8s.NewZarfManagedNamespace(ZarfNamespaceName) if _, err := c.CreateNamespace(zarfNamespace); err != nil { return fmt.Errorf("unable to create the zarf namespace: %w", err) } @@ -241,7 +241,7 @@ func (c *Cluster) SaveZarfState(state *types.ZarfState) error { Name: ZarfStateSecretName, Namespace: ZarfNamespaceName, Labels: map[string]string{ - config.ZarfManagedByLabel: "zarf", + k8s.ZarfManagedByLabel: "zarf", }, }, Type: corev1.SecretTypeOpaque, diff --git a/src/pkg/cluster/zarf.go b/src/pkg/cluster/zarf.go index afef2362b3..78dab6fc75 100644 --- a/src/pkg/cluster/zarf.go +++ b/src/pkg/cluster/zarf.go @@ -13,6 +13,7 @@ import ( "time" "github.com/defenseunicorns/zarf/src/config" + "github.com/defenseunicorns/zarf/src/pkg/k8s" "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/types" autoscalingV2 "k8s.io/api/autoscaling/v2" @@ -69,16 +70,16 @@ func (c *Cluster) StripZarfLabelsAndSecretsFromNamespaces() { deleteOptions := metav1.DeleteOptions{} listOptions := metav1.ListOptions{ - LabelSelector: config.ZarfManagedByLabel + "=zarf", + LabelSelector: k8s.ZarfManagedByLabel + "=zarf", } if namespaces, err := c.GetNamespaces(); err != nil { spinner.Errorf(err, "Unable to get k8s namespaces") } else { for _, namespace := range namespaces.Items { - if _, ok := namespace.Labels[agentLabel]; ok { + if _, ok := namespace.Labels[k8s.AgentLabel]; ok { spinner.Updatef("Removing Zarf Agent label for namespace %s", namespace.Name) - delete(namespace.Labels, agentLabel) + delete(namespace.Labels, k8s.AgentLabel) namespaceCopy := namespace if _, err = c.UpdateNamespace(&namespaceCopy); err != nil { // This is not a hard failure, but we should log it diff --git a/src/pkg/k8s/common.go b/src/pkg/k8s/common.go index e3472d8962..b4eaab2e66 100644 --- a/src/pkg/k8s/common.go +++ b/src/pkg/k8s/common.go @@ -20,11 +20,15 @@ import ( "k8s.io/client-go/tools/clientcmd" ) -// cannot import config.ZarfManagedByLabel due to import cycle -const zarfManagedByLabel = "app.kubernetes.io/managed-by" +const ( + //ZarfManagedByLabel is used to denote Zarf manages the lifecycle of a resource + ZarfManagedByLabel = "app.kubernetes.io/managed-by" + //AgentLabel is used to give instructions to the Zarf agent + AgentLabel = "zarf.dev/agent" +) // New creates a new K8s client. -func New(logger Log, defaultLabels Labels) (*K8s, error) { +func New(logger Log) (*K8s, error) { klog.SetLogger(funcr.New(func(_, args string) { logger(args) }, funcr.Options{})) @@ -38,13 +42,12 @@ func New(logger Log, defaultLabels Labels) (*K8s, error) { RestConfig: config, Clientset: clientset, Log: logger, - Labels: defaultLabels, }, nil } // NewWithWait is a convenience function that creates a new K8s client and waits for the cluster to be healthy. -func NewWithWait(logger Log, defaultLabels Labels, timeout time.Duration) (*K8s, error) { - k, err := New(logger, defaultLabels) +func NewWithWait(logger Log, timeout time.Duration) (*K8s, error) { + k, err := New(logger) if err != nil { return nil, err } diff --git a/src/pkg/k8s/namespace.go b/src/pkg/k8s/namespace.go index 2862731e90..015e7a0eda 100644 --- a/src/pkg/k8s/namespace.go +++ b/src/pkg/k8s/namespace.go @@ -20,6 +20,12 @@ func (k *K8s) GetNamespaces() (*corev1.NamespaceList, error) { return k.Clientset.CoreV1().Namespaces().List(context.TODO(), metaOptions) } +// GetNamespace gets a namespace by name +func (k *K8s) GetNamespace(name string) (*corev1.Namespace, error) { + getOptions := metav1.GetOptions{} + return k.Clientset.CoreV1().Namespaces().Get(context.TODO(), name, getOptions) +} + // UpdateNamespace updates the given namespace in the cluster. func (k *K8s) UpdateNamespace(namespace *corev1.Namespace) (*corev1.Namespace, error) { updateOptions := metav1.UpdateOptions{} @@ -62,19 +68,28 @@ func (k *K8s) DeleteNamespace(ctx context.Context, name string) error { } // NewZarfManagedNamespace returns a corev1.Namespace with Zarf-managed labels -func (k *K8s) NewZarfManagedNamespace(name string) *corev1.Namespace { - return &corev1.Namespace{ +func NewZarfManagedNamespace(name string) *corev1.Namespace { + namespace := &corev1.Namespace{ TypeMeta: metav1.TypeMeta{ APIVersion: corev1.SchemeGroupVersion.String(), Kind: "Namespace", }, ObjectMeta: metav1.ObjectMeta{ Name: name, - Labels: map[string]string{ - zarfManagedByLabel: "zarf", - }, }, } + namespace = UpdateNamespaceToBeZarfManaged(namespace) + return namespace +} + +// UpdateNamespaceToBeZarfManaged adds & deletes labels to a namespace go object which will signal Zarf to manage it +func UpdateNamespaceToBeZarfManaged(namespace *corev1.Namespace) *corev1.Namespace { + if namespace.Labels == nil { + namespace.Labels = make(map[string]string) + } + namespace.Labels[ZarfManagedByLabel] = "zarf" + delete(namespace.Labels, AgentLabel) + return namespace } // IsInitialNamespace returns true if the given namespace name is an initial k8s namespace: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/#initial-namespaces diff --git a/src/pkg/k8s/secrets.go b/src/pkg/k8s/secrets.go index f92882b8d0..88e7d62b58 100644 --- a/src/pkg/k8s/secrets.go +++ b/src/pkg/k8s/secrets.go @@ -36,7 +36,7 @@ func (k *K8s) GenerateSecret(namespace, name string, secretType corev1.SecretTyp Name: name, Namespace: namespace, Labels: map[string]string{ - zarfManagedByLabel: "zarf", + ZarfManagedByLabel: "zarf", }, }, Type: secretType, diff --git a/src/pkg/k8s/types.go b/src/pkg/k8s/types.go index 2326edbc98..d52ea6389b 100644 --- a/src/pkg/k8s/types.go +++ b/src/pkg/k8s/types.go @@ -21,7 +21,6 @@ type K8s struct { Clientset kubernetes.Interface RestConfig *rest.Config Log Log - Labels Labels } // PodLookup is a struct for specifying a pod to target for data injection or lookups. diff --git a/src/pkg/packager/deploy.go b/src/pkg/packager/deploy.go index 181a52cb42..b744ab79ab 100644 --- a/src/pkg/packager/deploy.go +++ b/src/pkg/packager/deploy.go @@ -447,7 +447,7 @@ func (p *Packager) setupState() (err error) { // Try to create the zarf namespace spinner.Updatef("Creating the Zarf namespace") - zarfNamespace := p.cluster.NewZarfManagedNamespace(cluster.ZarfNamespaceName) + zarfNamespace := k8s.NewZarfManagedNamespace(cluster.ZarfNamespaceName) if _, err := p.cluster.CreateNamespace(zarfNamespace); err != nil { spinner.Fatalf(err, "Unable to create the zarf namespace") } diff --git a/src/test/e2e/25_helm_test.go b/src/test/e2e/25_helm_test.go index e09d6cf47f..7c643288c0 100644 --- a/src/test/e2e/25_helm_test.go +++ b/src/test/e2e/25_helm_test.go @@ -189,6 +189,13 @@ func testHelmAdoption(t *testing.T) { require.NoError(t, err) require.Contains(t, string(helmOut), "zarf-f53a99d4a4dd9a3575bedf59cd42d48d751ae866") + existingLabel, _, err := e2e.Kubectl("get", "ns", "dos-games", "-o=jsonpath={.metadata.labels.keep-this}") + require.Equal(t, "label", existingLabel) + require.NoError(t, err) + existingAnnotation, _, err := e2e.Kubectl("get", "ns", "dos-games", "-o=jsonpath={.metadata.annotations.keep-this}") + require.Equal(t, "annotation", existingAnnotation) + require.NoError(t, err) + // Remove the package. stdOut, stdErr, err = e2e.Zarf("package", "remove", "dos-games", "--confirm") require.NoError(t, err, stdOut, stdErr) diff --git a/src/test/packages/25-manifest-adoption/deployment.yaml b/src/test/packages/25-manifest-adoption/deployment.yaml index c5779b20f0..9cd8c5b754 100644 --- a/src/test/packages/25-manifest-adoption/deployment.yaml +++ b/src/test/packages/25-manifest-adoption/deployment.yaml @@ -2,6 +2,10 @@ apiVersion: v1 kind: Namespace metadata: name: dos-games + labels: + keep-this: label + annotations: + keep-this: annotation --- # This is a normal deployment manifest for dos-games that should be "adopted" by Helm/Zarf apiVersion: apps/v1 From 91db0ad728791783ab55c2d909398b4f189c88bb Mon Sep 17 00:00:00 2001 From: Austin Abro <37223396+AustinAbro321@users.noreply.github.com> Date: Fri, 10 May 2024 16:52:16 -0400 Subject: [PATCH 02/12] Apply suggestions from code review Co-authored-by: Lucas Rodriguez --- src/internal/packager/helm/post-render.go | 2 +- src/pkg/cluster/injector.go | 2 +- src/pkg/k8s/common.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/internal/packager/helm/post-render.go b/src/internal/packager/helm/post-render.go index b9adfef568..c2c0cd8cfb 100644 --- a/src/internal/packager/helm/post-render.go +++ b/src/internal/packager/helm/post-render.go @@ -39,7 +39,7 @@ func (h *Helm) newRenderer() (*renderer, error) { if h.cluster != nil { namespace, err := h.cluster.K8s.GetNamespace(h.chart.Namespace) if err != nil && !errors.IsNotFound(err) { - return nil, fmt.Errorf("unable to check for existing namespace %q in cluster: %s", h.chart.Namespace, err) + return nil, fmt.Errorf("unable to check for existing namespace %q in cluster: %w", h.chart.Namespace, err) } if h.cfg.DeployOpts.AdoptExistingResources && !errors.IsNotFound(err) { namespaces[h.chart.Namespace] = k8s.UpdateNamespaceToBeZarfManaged(namespace) diff --git a/src/pkg/cluster/injector.go b/src/pkg/cluster/injector.go index fb642203d9..ca5ac4e0bd 100644 --- a/src/pkg/cluster/injector.go +++ b/src/pkg/cluster/injector.go @@ -321,7 +321,7 @@ func (c *Cluster) buildInjectionPod(node, image string, payloadConfigmaps []stri pod.Labels["app"] = "zarf-injector" // Ensure zarf agent doesn't break the injector on future runs - pod.Labels[k8s.ZarfManagedByLabel] = "ignore" + pod.Labels[k8s.AgentLabel] = "ignore" // Bind the pod to the node the image was found on pod.Spec.NodeName = node diff --git a/src/pkg/k8s/common.go b/src/pkg/k8s/common.go index b4eaab2e66..0170df8229 100644 --- a/src/pkg/k8s/common.go +++ b/src/pkg/k8s/common.go @@ -21,9 +21,9 @@ import ( ) const ( - //ZarfManagedByLabel is used to denote Zarf manages the lifecycle of a resource + // ZarfManagedByLabel is used to denote Zarf manages the lifecycle of a resource ZarfManagedByLabel = "app.kubernetes.io/managed-by" - //AgentLabel is used to give instructions to the Zarf agent + // AgentLabel is used to give instructions to the Zarf agent AgentLabel = "zarf.dev/agent" ) From c4077625d4bf88765d727add5817536ca808dc0d Mon Sep 17 00:00:00 2001 From: Austin Abro <37223396+AustinAbro321@users.noreply.github.com> Date: Mon, 13 May 2024 08:11:13 -0400 Subject: [PATCH 03/12] Update src/internal/packager/helm/post-render.go Co-authored-by: Philip Laine --- src/internal/packager/helm/post-render.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/packager/helm/post-render.go b/src/internal/packager/helm/post-render.go index c2c0cd8cfb..553c9a49d0 100644 --- a/src/internal/packager/helm/post-render.go +++ b/src/internal/packager/helm/post-render.go @@ -178,7 +178,7 @@ func (r *renderer) editHelmResources(resources []releaseutil.Manifest, finalMani switch rawData.GetKind() { case "Namespace": - namespace := new(corev1.Namespace) + namespace := &corev1.Namespace{} // parse the namespace resource so it can be applied out-of-band by zarf instead of helm to avoid helm ns shenanigans if err := runtime.DefaultUnstructuredConverter.FromUnstructured(rawData.UnstructuredContent(), namespace); err != nil { message.WarnErrf(err, "could not parse namespace %s", rawData.GetName()) From 11feb73b188edb51caa84cb0f3ff6b728a2b3d02 Mon Sep 17 00:00:00 2001 From: Austin Abro Date: Mon, 13 May 2024 12:16:53 +0000 Subject: [PATCH 04/12] refactor newrenderer --- src/internal/packager/helm/post-render.go | 35 +++++++++++------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/internal/packager/helm/post-render.go b/src/internal/packager/helm/post-render.go index 553c9a49d0..954860e478 100644 --- a/src/internal/packager/helm/post-render.go +++ b/src/internal/packager/helm/post-render.go @@ -35,25 +35,24 @@ type renderer struct { func (h *Helm) newRenderer() (*renderer, error) { message.Debugf("helm.NewRenderer()") - namespaces := make(map[string]*corev1.Namespace) - if h.cluster != nil { - namespace, err := h.cluster.K8s.GetNamespace(h.chart.Namespace) - if err != nil && !errors.IsNotFound(err) { - return nil, fmt.Errorf("unable to check for existing namespace %q in cluster: %w", h.chart.Namespace, err) - } - if h.cfg.DeployOpts.AdoptExistingResources && !errors.IsNotFound(err) { - namespaces[h.chart.Namespace] = k8s.UpdateNamespaceToBeZarfManaged(namespace) - } else { - namespaces[h.chart.Namespace] = k8s.NewZarfManagedNamespace(h.chart.Namespace) - } - - } - - return &renderer{ + rend := &renderer{ Helm: h, - connectStrings: make(types.ConnectStrings), - namespaces: namespaces, - }, nil + connectStrings: types.ConnectStrings{}, + namespaces: map[string]*corev1.Namespace{}, + } + if h.cluster == nil { + return rend, nil + } + namespace, err := h.cluster.K8s.GetNamespace(h.chart.Namespace) + if err != nil && !errors.IsNotFound(err) { + return nil, fmt.Errorf("unable to check for existing namespace %q in cluster: %w", h.chart.Namespace, err) + } + if h.cfg.DeployOpts.AdoptExistingResources && !errors.IsNotFound(err) { + rend.namespaces[h.chart.Namespace] = k8s.UpdateNamespaceToBeZarfManaged(namespace) + } else { + rend.namespaces[h.chart.Namespace] = k8s.NewZarfManagedNamespace(h.chart.Namespace) + } + return rend, nil } func (r *renderer) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer, error) { From aedd6b2765dc6d0d2bf9acf8af0d6b66354cee7a Mon Sep 17 00:00:00 2001 From: Austin Abro Date: Mon, 13 May 2024 19:21:00 +0000 Subject: [PATCH 05/12] clean --- src/internal/packager/helm/post-render.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/internal/packager/helm/post-render.go b/src/internal/packager/helm/post-render.go index 954860e478..0a9b99e7d5 100644 --- a/src/internal/packager/helm/post-render.go +++ b/src/internal/packager/helm/post-render.go @@ -183,10 +183,8 @@ func (r *renderer) editHelmResources(resources []releaseutil.Manifest, finalMani message.WarnErrf(err, "could not parse namespace %s", rawData.GetName()) } else { message.Debugf("Matched helm namespace %s for zarf annotation", namespace.Name) - namespace = k8s.UpdateNamespaceToBeZarfManaged(namespace) - // Add it to the stack - r.namespaces[namespace.Name] = namespace + r.namespaces[namespace.Name] = k8s.UpdateNamespaceToBeZarfManaged(namespace) } // skip so we can strip namespaces from helm's brain continue From 6ad1e2441c84a270e4b321f4e01f4eed0fe9027f Mon Sep 17 00:00:00 2001 From: Austin Abro <37223396+AustinAbro321@users.noreply.github.com> Date: Mon, 13 May 2024 15:21:12 -0400 Subject: [PATCH 06/12] Update src/internal/packager/helm/post-render.go Co-authored-by: Lucas Rodriguez --- src/internal/packager/helm/post-render.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/packager/helm/post-render.go b/src/internal/packager/helm/post-render.go index 0a9b99e7d5..cde8d79b65 100644 --- a/src/internal/packager/helm/post-render.go +++ b/src/internal/packager/helm/post-render.go @@ -43,7 +43,7 @@ func (h *Helm) newRenderer() (*renderer, error) { if h.cluster == nil { return rend, nil } - namespace, err := h.cluster.K8s.GetNamespace(h.chart.Namespace) + namespace, err := h.cluster.GetNamespace(h.chart.Namespace) if err != nil && !errors.IsNotFound(err) { return nil, fmt.Errorf("unable to check for existing namespace %q in cluster: %w", h.chart.Namespace, err) } From 60dd29e5aad8002d5288fc4c92b896dc3f8fe67a Mon Sep 17 00:00:00 2001 From: Austin Abro Date: Mon, 13 May 2024 19:27:31 +0000 Subject: [PATCH 07/12] rework bools --- src/internal/packager/helm/post-render.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/internal/packager/helm/post-render.go b/src/internal/packager/helm/post-render.go index 0a9b99e7d5..347aa09a60 100644 --- a/src/internal/packager/helm/post-render.go +++ b/src/internal/packager/helm/post-render.go @@ -47,11 +47,12 @@ func (h *Helm) newRenderer() (*renderer, error) { if err != nil && !errors.IsNotFound(err) { return nil, fmt.Errorf("unable to check for existing namespace %q in cluster: %w", h.chart.Namespace, err) } - if h.cfg.DeployOpts.AdoptExistingResources && !errors.IsNotFound(err) { - rend.namespaces[h.chart.Namespace] = k8s.UpdateNamespaceToBeZarfManaged(namespace) - } else { + if errors.IsNotFound(err) { rend.namespaces[h.chart.Namespace] = k8s.NewZarfManagedNamespace(h.chart.Namespace) + } else if h.cfg.DeployOpts.AdoptExistingResources { + rend.namespaces[h.chart.Namespace] = k8s.UpdateNamespaceToBeZarfManaged(namespace) } + return rend, nil } From b230b2d6524341ea73ce1ad48345bb69c654dc40 Mon Sep 17 00:00:00 2001 From: Austin Abro Date: Mon, 13 May 2024 19:45:58 +0000 Subject: [PATCH 08/12] zarf managed labels --- src/internal/packager/helm/post-render.go | 6 ++++-- src/pkg/k8s/namespace.go | 16 ++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/internal/packager/helm/post-render.go b/src/internal/packager/helm/post-render.go index 790f6b3975..65df991876 100644 --- a/src/internal/packager/helm/post-render.go +++ b/src/internal/packager/helm/post-render.go @@ -50,7 +50,8 @@ func (h *Helm) newRenderer() (*renderer, error) { if errors.IsNotFound(err) { rend.namespaces[h.chart.Namespace] = k8s.NewZarfManagedNamespace(h.chart.Namespace) } else if h.cfg.DeployOpts.AdoptExistingResources { - rend.namespaces[h.chart.Namespace] = k8s.UpdateNamespaceToBeZarfManaged(namespace) + namespace.Labels = k8s.AdoptZarfManagedLabels(namespace.Labels) + rend.namespaces[h.chart.Namespace] = namespace } return rend, nil @@ -184,8 +185,9 @@ func (r *renderer) editHelmResources(resources []releaseutil.Manifest, finalMani message.WarnErrf(err, "could not parse namespace %s", rawData.GetName()) } else { message.Debugf("Matched helm namespace %s for zarf annotation", namespace.Name) + namespace.Labels = k8s.AdoptZarfManagedLabels(namespace.Labels) // Add it to the stack - r.namespaces[namespace.Name] = k8s.UpdateNamespaceToBeZarfManaged(namespace) + r.namespaces[namespace.Name] = namespace } // skip so we can strip namespaces from helm's brain continue diff --git a/src/pkg/k8s/namespace.go b/src/pkg/k8s/namespace.go index 015e7a0eda..54e1e06150 100644 --- a/src/pkg/k8s/namespace.go +++ b/src/pkg/k8s/namespace.go @@ -78,18 +78,18 @@ func NewZarfManagedNamespace(name string) *corev1.Namespace { Name: name, }, } - namespace = UpdateNamespaceToBeZarfManaged(namespace) + namespace.Labels = AdoptZarfManagedLabels(namespace.Labels) return namespace } -// UpdateNamespaceToBeZarfManaged adds & deletes labels to a namespace go object which will signal Zarf to manage it -func UpdateNamespaceToBeZarfManaged(namespace *corev1.Namespace) *corev1.Namespace { - if namespace.Labels == nil { - namespace.Labels = make(map[string]string) +// AdoptZarfManagedLabels adds & deletes the necessary labels that signal to Zarf it should manage a namespace +func AdoptZarfManagedLabels(labels map[string]string) map[string]string { + if labels == nil { + labels = make(map[string]string) } - namespace.Labels[ZarfManagedByLabel] = "zarf" - delete(namespace.Labels, AgentLabel) - return namespace + labels[ZarfManagedByLabel] = "zarf" + delete(labels, AgentLabel) + return labels } // IsInitialNamespace returns true if the given namespace name is an initial k8s namespace: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/#initial-namespaces From f9b4ec419b7de6b52fa439469287c0577d8b8463 Mon Sep 17 00:00:00 2001 From: Austin Abro Date: Wed, 15 May 2024 20:08:27 +0000 Subject: [PATCH 09/12] cluster k8s rearranging --- src/internal/packager/helm/post-render.go | 10 ++++---- src/pkg/cluster/namespace.go | 28 +++++++++++++++++++++++ src/pkg/cluster/state.go | 2 +- src/pkg/k8s/namespace.go | 25 -------------------- src/pkg/packager/deploy.go | 2 +- 5 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/internal/packager/helm/post-render.go b/src/internal/packager/helm/post-render.go index 6d450ab863..f798db8b78 100644 --- a/src/internal/packager/helm/post-render.go +++ b/src/internal/packager/helm/post-render.go @@ -14,7 +14,7 @@ import ( "github.com/defenseunicorns/pkg/helpers" "github.com/defenseunicorns/zarf/src/config" - "github.com/defenseunicorns/zarf/src/pkg/k8s" + "github.com/defenseunicorns/zarf/src/pkg/cluster" "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/pkg/utils" "github.com/defenseunicorns/zarf/src/types" @@ -49,9 +49,9 @@ func (h *Helm) newRenderer() (*renderer, error) { return nil, fmt.Errorf("unable to check for existing namespace %q in cluster: %w", h.chart.Namespace, err) } if errors.IsNotFound(err) { - rend.namespaces[h.chart.Namespace] = k8s.NewZarfManagedNamespace(h.chart.Namespace) + rend.namespaces[h.chart.Namespace] = cluster.NewZarfManagedNamespace(h.chart.Namespace) } else if h.cfg.DeployOpts.AdoptExistingResources { - namespace.Labels = k8s.AdoptZarfManagedLabels(namespace.Labels) + namespace.Labels = cluster.AdoptZarfManagedLabels(namespace.Labels) rend.namespaces[h.chart.Namespace] = namespace } @@ -187,7 +187,7 @@ func (r *renderer) editHelmResources(ctx context.Context, resources []releaseuti message.WarnErrf(err, "could not parse namespace %s", rawData.GetName()) } else { message.Debugf("Matched helm namespace %s for zarf annotation", namespace.Name) - namespace.Labels = k8s.AdoptZarfManagedLabels(namespace.Labels) + namespace.Labels = cluster.AdoptZarfManagedLabels(namespace.Labels) // Add it to the stack r.namespaces[namespace.Name] = namespace } @@ -214,7 +214,7 @@ func (r *renderer) editHelmResources(ctx context.Context, resources []releaseuti namespace := rawData.GetNamespace() if _, exists := r.namespaces[namespace]; !exists && namespace != "" { // if this is the first time seeing this ns, we need to track that to create it as well - r.namespaces[namespace] = k8s.NewZarfManagedNamespace(namespace) + r.namespaces[namespace] = cluster.NewZarfManagedNamespace(namespace) } // If we have been asked to adopt existing resources, process those now as well diff --git a/src/pkg/cluster/namespace.go b/src/pkg/cluster/namespace.go index a7209936b3..56a8566834 100644 --- a/src/pkg/cluster/namespace.go +++ b/src/pkg/cluster/namespace.go @@ -7,7 +7,10 @@ package cluster import ( "context" + "github.com/defenseunicorns/zarf/src/pkg/k8s" "github.com/defenseunicorns/zarf/src/pkg/message" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // DeleteZarfNamespace deletes the Zarf namespace from the connected cluster. @@ -17,3 +20,28 @@ func (c *Cluster) DeleteZarfNamespace(ctx context.Context) error { return c.DeleteNamespace(ctx, ZarfNamespaceName) } + +// NewZarfManagedNamespace returns a corev1.Namespace with Zarf-managed labels +func NewZarfManagedNamespace(name string) *corev1.Namespace { + namespace := &corev1.Namespace{ + TypeMeta: metav1.TypeMeta{ + APIVersion: corev1.SchemeGroupVersion.String(), + Kind: "Namespace", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + } + namespace.Labels = AdoptZarfManagedLabels(namespace.Labels) + return namespace +} + +// AdoptZarfManagedLabels adds & deletes the necessary labels that signal to Zarf it should manage a namespace +func AdoptZarfManagedLabels(labels map[string]string) map[string]string { + if labels == nil { + labels = make(map[string]string) + } + labels[k8s.ZarfManagedByLabel] = "zarf" + delete(labels, k8s.AgentLabel) + return labels +} diff --git a/src/pkg/cluster/state.go b/src/pkg/cluster/state.go index 78ba1cdc4e..2d51aa38d4 100644 --- a/src/pkg/cluster/state.go +++ b/src/pkg/cluster/state.go @@ -102,7 +102,7 @@ func (c *Cluster) InitZarfState(ctx context.Context, initOptions types.ZarfInitO // Try to create the zarf namespace. spinner.Updatef("Creating the Zarf namespace") - zarfNamespace := k8s.NewZarfManagedNamespace(ZarfNamespaceName) + zarfNamespace := NewZarfManagedNamespace(ZarfNamespaceName) if _, err := c.CreateNamespace(ctx, zarfNamespace); err != nil { return fmt.Errorf("unable to create the zarf namespace: %w", err) } diff --git a/src/pkg/k8s/namespace.go b/src/pkg/k8s/namespace.go index 65da03f049..abf882b457 100644 --- a/src/pkg/k8s/namespace.go +++ b/src/pkg/k8s/namespace.go @@ -73,31 +73,6 @@ func (k *K8s) DeleteNamespace(ctx context.Context, name string) error { } } -// NewZarfManagedNamespace returns a corev1.Namespace with Zarf-managed labels -func NewZarfManagedNamespace(name string) *corev1.Namespace { - namespace := &corev1.Namespace{ - TypeMeta: metav1.TypeMeta{ - APIVersion: corev1.SchemeGroupVersion.String(), - Kind: "Namespace", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: name, - }, - } - namespace.Labels = AdoptZarfManagedLabels(namespace.Labels) - return namespace -} - -// AdoptZarfManagedLabels adds & deletes the necessary labels that signal to Zarf it should manage a namespace -func AdoptZarfManagedLabels(labels map[string]string) map[string]string { - if labels == nil { - labels = make(map[string]string) - } - labels[ZarfManagedByLabel] = "zarf" - delete(labels, AgentLabel) - return labels -} - // IsInitialNamespace returns true if the given namespace name is an initial k8s namespace: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/#initial-namespaces func (k *K8s) IsInitialNamespace(name string) bool { if name == "default" { diff --git a/src/pkg/packager/deploy.go b/src/pkg/packager/deploy.go index a90681aedd..a7c516fb43 100644 --- a/src/pkg/packager/deploy.go +++ b/src/pkg/packager/deploy.go @@ -448,7 +448,7 @@ func (p *Packager) setupState(ctx context.Context) (err error) { // Try to create the zarf namespace spinner.Updatef("Creating the Zarf namespace") - zarfNamespace := k8s.NewZarfManagedNamespace(cluster.ZarfNamespaceName) + zarfNamespace := cluster.NewZarfManagedNamespace(cluster.ZarfNamespaceName) if _, err := p.cluster.CreateNamespace(ctx, zarfNamespace); err != nil { spinner.Fatalf(err, "Unable to create the zarf namespace") } From 18c3d8e5ada92a41df260974bc3708a93552dfaa Mon Sep 17 00:00:00 2001 From: Austin Abro Date: Wed, 15 May 2024 20:36:39 +0000 Subject: [PATCH 10/12] context --- src/internal/packager/helm/post-render.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/internal/packager/helm/post-render.go b/src/internal/packager/helm/post-render.go index f798db8b78..3cdaa9c405 100644 --- a/src/internal/packager/helm/post-render.go +++ b/src/internal/packager/helm/post-render.go @@ -23,6 +23,7 @@ import ( "sigs.k8s.io/yaml" "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" ) @@ -31,6 +32,7 @@ type renderer struct { *Helm connectStrings types.ConnectStrings namespaces map[string]*corev1.Namespace + ctx context.Context } func (h *Helm) newRenderer() (*renderer, error) { @@ -40,11 +42,13 @@ func (h *Helm) newRenderer() (*renderer, error) { Helm: h, connectStrings: types.ConnectStrings{}, namespaces: map[string]*corev1.Namespace{}, + ctx: context.Background(), } if h.cluster == nil { return rend, nil } - namespace, err := h.cluster.GetNamespace(h.chart.Namespace) + + namespace, err := h.cluster.Clientset.CoreV1().Namespaces().Get(rend.ctx, h.chart.Namespace, metav1.GetOptions{}) if err != nil && !errors.IsNotFound(err) { return nil, fmt.Errorf("unable to check for existing namespace %q in cluster: %w", h.chart.Namespace, err) } @@ -94,13 +98,12 @@ func (r *renderer) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer, error) { finalManifestsOutput := bytes.NewBuffer(nil) if r.cluster != nil { - ctx := context.Background() - if err := r.editHelmResources(ctx, resources, finalManifestsOutput); err != nil { + if err := r.editHelmResources(r.ctx, resources, finalManifestsOutput); err != nil { return nil, err } - if err := r.adoptAndUpdateNamespaces(ctx); err != nil { + if err := r.adoptAndUpdateNamespaces(r.ctx); err != nil { return nil, err } } else { From 2239b9a046b40e28985bf4f667d60c45d3d5d5e6 Mon Sep 17 00:00:00 2001 From: Austin Abro Date: Thu, 16 May 2024 11:45:06 +0000 Subject: [PATCH 11/12] fixing context things --- src/internal/packager/helm/post-render.go | 9 ++++----- src/pkg/k8s/namespace.go | 6 ------ 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/internal/packager/helm/post-render.go b/src/internal/packager/helm/post-render.go index 3cdaa9c405..6d7c56f7f2 100644 --- a/src/internal/packager/helm/post-render.go +++ b/src/internal/packager/helm/post-render.go @@ -32,7 +32,6 @@ type renderer struct { *Helm connectStrings types.ConnectStrings namespaces map[string]*corev1.Namespace - ctx context.Context } func (h *Helm) newRenderer() (*renderer, error) { @@ -42,13 +41,12 @@ func (h *Helm) newRenderer() (*renderer, error) { Helm: h, connectStrings: types.ConnectStrings{}, namespaces: map[string]*corev1.Namespace{}, - ctx: context.Background(), } if h.cluster == nil { return rend, nil } - namespace, err := h.cluster.Clientset.CoreV1().Namespaces().Get(rend.ctx, h.chart.Namespace, metav1.GetOptions{}) + namespace, err := h.cluster.Clientset.CoreV1().Namespaces().Get(context.TODO(), h.chart.Namespace, metav1.GetOptions{}) if err != nil && !errors.IsNotFound(err) { return nil, fmt.Errorf("unable to check for existing namespace %q in cluster: %w", h.chart.Namespace, err) } @@ -98,12 +96,13 @@ func (r *renderer) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer, error) { finalManifestsOutput := bytes.NewBuffer(nil) if r.cluster != nil { + ctx := context.Background() - if err := r.editHelmResources(r.ctx, resources, finalManifestsOutput); err != nil { + if err := r.editHelmResources(ctx, resources, finalManifestsOutput); err != nil { return nil, err } - if err := r.adoptAndUpdateNamespaces(r.ctx); err != nil { + if err := r.adoptAndUpdateNamespaces(ctx); err != nil { return nil, err } } else { diff --git a/src/pkg/k8s/namespace.go b/src/pkg/k8s/namespace.go index abf882b457..2f1d43d019 100644 --- a/src/pkg/k8s/namespace.go +++ b/src/pkg/k8s/namespace.go @@ -20,12 +20,6 @@ func (k *K8s) GetNamespaces(ctx context.Context) (*corev1.NamespaceList, error) return k.Clientset.CoreV1().Namespaces().List(ctx, metaOptions) } -// GetNamespace gets a namespace by name -func (k *K8s) GetNamespace(name string) (*corev1.Namespace, error) { - getOptions := metav1.GetOptions{} - return k.Clientset.CoreV1().Namespaces().Get(context.TODO(), name, getOptions) -} - // UpdateNamespace updates the given namespace in the cluster. func (k *K8s) UpdateNamespace(ctx context.Context, namespace *corev1.Namespace) (*corev1.Namespace, error) { updateOptions := metav1.UpdateOptions{} From ec15b679f3def10f82dfd556d449957e249c312f Mon Sep 17 00:00:00 2001 From: Austin Abro Date: Fri, 17 May 2024 14:40:53 +0000 Subject: [PATCH 12/12] import rename --- src/internal/packager/helm/post-render.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/internal/packager/helm/post-render.go b/src/internal/packager/helm/post-render.go index 6d7c56f7f2..4be00a1b11 100644 --- a/src/internal/packager/helm/post-render.go +++ b/src/internal/packager/helm/post-render.go @@ -22,7 +22,7 @@ import ( corev1 "k8s.io/api/core/v1" "sigs.k8s.io/yaml" - "k8s.io/apimachinery/pkg/api/errors" + kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -47,10 +47,10 @@ func (h *Helm) newRenderer() (*renderer, error) { } namespace, err := h.cluster.Clientset.CoreV1().Namespaces().Get(context.TODO(), h.chart.Namespace, metav1.GetOptions{}) - if err != nil && !errors.IsNotFound(err) { + if err != nil && !kerrors.IsNotFound(err) { return nil, fmt.Errorf("unable to check for existing namespace %q in cluster: %w", h.chart.Namespace, err) } - if errors.IsNotFound(err) { + if kerrors.IsNotFound(err) { rend.namespaces[h.chart.Namespace] = cluster.NewZarfManagedNamespace(h.chart.Namespace) } else if h.cfg.DeployOpts.AdoptExistingResources { namespace.Labels = cluster.AdoptZarfManagedLabels(namespace.Labels)