Skip to content

Commit

Permalink
Merge branch 'main' into feature/context-signal
Browse files Browse the repository at this point in the history
  • Loading branch information
AustinAbro321 committed Jun 3, 2024
2 parents 70c1866 + 0527bea commit 1cff560
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 208 deletions.
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ go 1.21.8
replace github.com/xeipuuv/gojsonschema => github.com/defenseunicorns/gojsonschema v0.0.0-20231116163348-e00f069122d6

require (
cuelang.org/go v0.7.0
github.com/AlecAivazis/survey/v2 v2.3.7
github.com/Masterminds/semver/v3 v3.2.1
github.com/agnivade/levenshtein v1.1.1
Expand Down Expand Up @@ -62,6 +61,8 @@ require (
sigs.k8s.io/yaml v1.4.0
)

require cuelang.org/go v0.7.0 // indirect

require (
atomicgo.dev/cursor v0.2.0 // indirect
atomicgo.dev/keyboard v0.2.9 // indirect
Expand Down
40 changes: 27 additions & 13 deletions src/internal/packager/git/gitea.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ import (
"encoding/json"
"fmt"
"io"
netHttp "net/http"
"os"
"time"

netHttp "net/http"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/defenseunicorns/zarf/src/config"
"github.com/defenseunicorns/zarf/src/pkg/cluster"
"github.com/defenseunicorns/zarf/src/pkg/k8s"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/types"
"k8s.io/apimachinery/pkg/runtime/schema"
)

// CreateTokenResponse is the response given from creating a token in Gitea
Expand Down Expand Up @@ -253,24 +253,38 @@ func UpdateGiteaPVC(ctx context.Context, shouldRollBack bool) (string, error) {
}

pvcName := os.Getenv("ZARF_VAR_GIT_SERVER_EXISTING_PVC")
groupKind := schema.GroupKind{
Group: "",
Kind: "PersistentVolumeClaim",
}
labels := map[string]string{"app.kubernetes.io/managed-by": "Helm"}
annotations := map[string]string{"meta.helm.sh/release-name": "zarf-gitea", "meta.helm.sh/release-namespace": "zarf"}

if shouldRollBack {
err = c.K8s.RemoveLabelsAndAnnotations(ctx, cluster.ZarfNamespaceName, pvcName, groupKind, labels, annotations)
return "false", err
pvc, err := c.Clientset.CoreV1().PersistentVolumeClaims(cluster.ZarfNamespaceName).Get(ctx, pvcName, metav1.GetOptions{})
if err != nil {
return "false", err
}
delete(pvc.Labels, "app.kubernetes.io/managed-by")
delete(pvc.Annotations, "meta.helm.sh/release-name")
delete(pvc.Annotations, "meta.helm.sh/release-namespace")
_, err = c.Clientset.CoreV1().PersistentVolumeClaims(cluster.ZarfNamespaceName).Update(ctx, pvc, metav1.UpdateOptions{})
if err != nil {
return "false", err
}
return "false", nil
}

if pvcName == "data-zarf-gitea-0" {
err = c.K8s.AddLabelsAndAnnotations(ctx, cluster.ZarfNamespaceName, pvcName, groupKind, labels, annotations)
return "true", err
pvc, err := c.Clientset.CoreV1().PersistentVolumeClaims(cluster.ZarfNamespaceName).Get(ctx, pvcName, metav1.GetOptions{})
if err != nil {
return "true", err
}
pvc.Labels["app.kubernetes.io/managed-by"] = "Helm"
pvc.Annotations["meta.helm.sh/release-name"] = "zarf-gitea"
pvc.Annotations["meta.helm.sh/release-namespace"] = "zarf"
_, err = c.Clientset.CoreV1().PersistentVolumeClaims(cluster.ZarfNamespaceName).Update(ctx, pvc, metav1.UpdateOptions{})
if err != nil {
return "true", err
}
return "true", nil
}

return "false", err
return "false", nil
}

// DoHTTPThings adds http request boilerplate and perform the request, checking for a successful response.
Expand Down
75 changes: 60 additions & 15 deletions src/internal/packager/helm/post-render.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"os"
"path/filepath"
"reflect"
"slices"

"github.com/defenseunicorns/pkg/helpers"
"github.com/defenseunicorns/zarf/src/config"
Expand All @@ -20,6 +21,8 @@ import (
"github.com/defenseunicorns/zarf/src/types"
"helm.sh/helm/v3/pkg/releaseutil"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/restmapper"
"sigs.k8s.io/yaml"

kerrors "k8s.io/apimachinery/pkg/api/errors"
Expand Down Expand Up @@ -117,29 +120,35 @@ func (r *renderer) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer, error) {

func (r *renderer) adoptAndUpdateNamespaces(ctx context.Context) error {
c := r.cluster
existingNamespaces, _ := c.GetNamespaces(ctx)
namespaceList, err := r.cluster.Clientset.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
if err != nil {
return err
}
for name, namespace := range r.namespaces {

// Check to see if this namespace already exists
var existingNamespace bool
for _, serverNamespace := range existingNamespaces.Items {
for _, serverNamespace := range namespaceList.Items {
if serverNamespace.Name == name {
existingNamespace = true
}
}

if !existingNamespace {
// This is a new namespace, add it
if _, err := c.CreateNamespace(ctx, namespace); err != nil {
_, err := c.Clientset.CoreV1().Namespaces().Create(ctx, namespace, metav1.CreateOptions{})
if err != nil {
return fmt.Errorf("unable to create the missing namespace %s", name)
}
} else if r.cfg.DeployOpts.AdoptExistingResources {
if r.cluster.IsInitialNamespace(name) {
// If this is a K8s initial namespace, refuse to adopt it
// Refuse to adopt namespace if it is one of four initial Kubernetes namespaces.
// https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/#initial-namespaces
if slices.Contains([]string{"default", "kube-node-lease", "kube-public", "kube-system"}, name) {
message.Warnf("Refusing to adopt the initial namespace: %s", name)
} else {
// This is an existing namespace to adopt
if _, err := c.UpdateNamespace(ctx, namespace); err != nil {
_, err := c.Clientset.CoreV1().Namespaces().Update(ctx, namespace, metav1.UpdateOptions{})
if err != nil {
return fmt.Errorf("unable to adopt the existing namespace %s", name)
}
}
Expand Down Expand Up @@ -174,6 +183,16 @@ func (r *renderer) adoptAndUpdateNamespaces(ctx context.Context) error {
}

func (r *renderer) editHelmResources(ctx context.Context, resources []releaseutil.Manifest, finalManifestsOutput *bytes.Buffer) error {
dc, err := dynamic.NewForConfig(r.cluster.RestConfig)
if err != nil {
return err
}
groupResources, err := restmapper.GetAPIGroupResources(r.cluster.Clientset.Discovery())
if err != nil {
return err
}
mapper := restmapper.NewDiscoveryRESTMapper(groupResources)

for _, resource := range resources {
// parse to unstructured to have access to more data than just the name
rawData := &unstructured.Unstructured{}
Expand All @@ -199,8 +218,13 @@ func (r *renderer) editHelmResources(ctx context.Context, resources []releaseuti
case "Service":
// Check service resources for the zarf-connect label
labels := rawData.GetLabels()
if labels == nil {
labels = map[string]string{}
}
annotations := rawData.GetAnnotations()

if annotations == nil {
annotations = map[string]string{}
}
if key, keyExists := labels[config.ZarfConnectLabelName]; keyExists {
// If there is a zarf-connect label
message.Debugf("Match helm service %s for zarf connection %s", rawData.GetName(), key)
Expand All @@ -226,14 +250,35 @@ func (r *renderer) editHelmResources(ctx context.Context, resources []releaseuti
deployedNamespace = r.chart.Namespace
}

helmLabels := map[string]string{"app.kubernetes.io/managed-by": "Helm"}
helmAnnotations := map[string]string{
"meta.helm.sh/release-name": r.chart.ReleaseName,
"meta.helm.sh/release-namespace": r.chart.Namespace,
}

if err := r.cluster.AddLabelsAndAnnotations(ctx, deployedNamespace, rawData.GetName(), rawData.GroupVersionKind().GroupKind(), helmLabels, helmAnnotations); err != nil {
// Print a debug message since this could just be because the resource doesn't exist
err := func() error {
mapping, err := mapper.RESTMapping(rawData.GroupVersionKind().GroupKind())
if err != nil {
return err
}
resource, err := dc.Resource(mapping.Resource).Namespace(deployedNamespace).Get(ctx, rawData.GetName(), metav1.GetOptions{})
if err != nil {
return err
}
labels := resource.GetLabels()
if labels == nil {
labels = map[string]string{}
}
labels["app.kubernetes.io/managed-by"] = "Helm"
resource.SetLabels(labels)
annotations := resource.GetAnnotations()
if annotations == nil {
annotations = map[string]string{}
}
annotations["meta.helm.sh/release-name"] = r.chart.ReleaseName
annotations["meta.helm.sh/release-namespace"] = r.chart.Namespace
resource.SetAnnotations(annotations)
_, err = dc.Resource(mapping.Resource).Namespace(deployedNamespace).Update(ctx, resource, metav1.UpdateOptions{})
if err != nil {
return err
}
return nil
}()
if err != nil {
message.Debugf("Unable to adopt resource %s: %s", rawData.GetName(), err.Error())
}
}
Expand Down
27 changes: 26 additions & 1 deletion src/pkg/cluster/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ package cluster

import (
"context"
"time"

"github.com/defenseunicorns/zarf/src/pkg/k8s"
"github.com/defenseunicorns/zarf/src/pkg/message"
corev1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand All @@ -18,7 +20,30 @@ func (c *Cluster) DeleteZarfNamespace(ctx context.Context) error {
spinner := message.NewProgressSpinner("Deleting the zarf namespace from this cluster")
defer spinner.Stop()

return c.DeleteNamespace(ctx, ZarfNamespaceName)
err := c.Clientset.CoreV1().Namespaces().Delete(ctx, ZarfNamespaceName, metav1.DeleteOptions{})
if kerrors.IsNotFound(err) {
return nil
}
if err != nil {
return err
}
timer := time.NewTimer(0)
defer timer.Stop()
for {
select {
case <-ctx.Done():
return ctx.Err()
case <-timer.C:
_, err := c.Clientset.CoreV1().Namespaces().Get(ctx, ZarfNamespaceName, metav1.GetOptions{})
if kerrors.IsNotFound(err) {
return nil
}
if err != nil {
return err
}
timer.Reset(1 * time.Second)
}
}
}

// NewZarfManagedNamespace returns a corev1.Namespace with Zarf-managed labels
Expand Down
11 changes: 7 additions & 4 deletions src/pkg/cluster/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"reflect"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/defenseunicorns/zarf/src/config"
"github.com/defenseunicorns/zarf/src/pkg/k8s"
Expand Down Expand Up @@ -80,11 +81,12 @@ func (c *Cluster) UpdateZarfManagedImageSecrets(ctx context.Context, state *type
spinner := message.NewProgressSpinner("Updating existing Zarf-managed image secrets")
defer spinner.Stop()

if namespaces, err := c.GetNamespaces(ctx); err != nil {
namespaceList, err := c.Clientset.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
if err != nil {
spinner.Errorf(err, "Unable to get k8s namespaces")
} else {
// Update all image pull secrets
for _, namespace := range namespaces.Items {
for _, namespace := range namespaceList.Items {
currentRegistrySecret, err := c.GetSecret(ctx, namespace.Name, config.ZarfImagePullSecretName)
if err != nil {
continue
Expand Down Expand Up @@ -115,11 +117,12 @@ func (c *Cluster) UpdateZarfManagedGitSecrets(ctx context.Context, state *types.
spinner := message.NewProgressSpinner("Updating existing Zarf-managed git secrets")
defer spinner.Stop()

if namespaces, err := c.GetNamespaces(ctx); err != nil {
namespaceList, err := c.Clientset.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
if err != nil {
spinner.Errorf(err, "Unable to get k8s namespaces")
} else {
// Update all git pull secrets
for _, namespace := range namespaces.Items {
for _, namespace := range namespaceList.Items {
currentGitSecret, err := c.GetSecret(ctx, namespace.Name, config.ZarfGitServerSecretName)
if err != nil {
continue
Expand Down
11 changes: 4 additions & 7 deletions src/pkg/cluster/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,12 @@ func (c *Cluster) InitZarfState(ctx context.Context, initOptions types.ZarfInitO
// Setup zarf agent PKI
state.AgentTLS = pki.GeneratePKI(config.ZarfAgentHost)

namespaces, err := c.GetNamespaces(ctx)
namespaceList, err := c.Clientset.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
if err != nil {
return fmt.Errorf("unable to get the Kubernetes namespaces: %w", err)
}
// Mark existing namespaces as ignored for the zarf agent to prevent mutating resources we don't own.
for _, namespace := range namespaces.Items {
// Skip Zarf namespace if it already exists.
if namespace.Name == ZarfNamespaceName {
continue
}
for _, namespace := range namespaceList.Items {
spinner.Updatef("Marking existing namespace %s as ignored by Zarf Agent", namespace.Name)
if namespace.Labels == nil {
// Ensure label map exists to avoid nil panic
Expand All @@ -105,7 +101,8 @@ func (c *Cluster) InitZarfState(ctx context.Context, initOptions types.ZarfInitO
// This label will tell the Zarf Agent to ignore this namespace.
namespace.Labels[k8s.AgentLabel] = "ignore"
namespaceCopy := namespace
if _, err = c.UpdateNamespace(ctx, &namespaceCopy); err != nil {
_, err := c.Clientset.CoreV1().Namespaces().Update(ctx, &namespaceCopy, metav1.UpdateOptions{})
if err != nil {
// This is not a hard failure, but we should log it.
message.WarnErrf(err, "Unable to mark the namespace %s as ignored by Zarf Agent", namespace.Name)
}
Expand Down
8 changes: 5 additions & 3 deletions src/pkg/cluster/zarf.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,17 @@ func (c *Cluster) StripZarfLabelsAndSecretsFromNamespaces(ctx context.Context) {
LabelSelector: k8s.ZarfManagedByLabel + "=zarf",
}

if namespaces, err := c.GetNamespaces(ctx); err != nil {
namespaceList, err := c.Clientset.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
if err != nil {
spinner.Errorf(err, "Unable to get k8s namespaces")
} else {
for _, namespace := range namespaces.Items {
for _, namespace := range namespaceList.Items {
if _, ok := namespace.Labels[k8s.AgentLabel]; ok {
spinner.Updatef("Removing Zarf Agent label for namespace %s", namespace.Name)
delete(namespace.Labels, k8s.AgentLabel)
namespaceCopy := namespace
if _, err = c.UpdateNamespace(ctx, &namespaceCopy); err != nil {
_, err := c.Clientset.CoreV1().Namespaces().Update(ctx, &namespaceCopy, metav1.UpdateOptions{})
if err != nil {
// This is not a hard failure, but we should log it
spinner.Errorf(err, "Unable to update the namespace labels for %s", namespace.Name)
}
Expand Down
Loading

0 comments on commit 1cff560

Please sign in to comment.