Skip to content

Commit

Permalink
refactor: remove k8s package (#2627)
Browse files Browse the repository at this point in the history
## Description

This is the final PR to completlty remove the k8s package. It refactors
some of the cluster creation and moves constants that are still needed.

## Related Issue

Fixes #2507 

## Checklist before merging

- [x] Test, docs, adr added or updated as needed
- [x] [Contributor Guide
Steps](https://github.com/defenseunicorns/zarf/blob/main/.github/CONTRIBUTING.md#developer-workflow)
followed

Co-authored-by: Austin Abro <37223396+AustinAbro321@users.noreply.github.com>
  • Loading branch information
phillebaba and AustinAbro321 committed Jun 21, 2024
1 parent 27f280d commit 1b104dc
Show file tree
Hide file tree
Showing 17 changed files with 176 additions and 296 deletions.
3 changes: 1 addition & 2 deletions src/internal/agent/hooks/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (

"github.com/defenseunicorns/zarf/src/internal/agent/operations"
"github.com/defenseunicorns/zarf/src/pkg/cluster"
"github.com/defenseunicorns/zarf/src/pkg/k8s"
"github.com/defenseunicorns/zarf/src/types"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/admission/v1"
Expand All @@ -32,7 +31,7 @@ type admissionTest struct {

func createTestClientWithZarfState(ctx context.Context, t *testing.T, state *types.ZarfState) *cluster.Cluster {
t.Helper()
c := &cluster.Cluster{K8s: &k8s.K8s{Clientset: fake.NewSimpleClientset()}}
c := &cluster.Cluster{Clientset: fake.NewSimpleClientset()}
stateData, err := json.Marshal(state)
require.NoError(t, err)

Expand Down
118 changes: 118 additions & 0 deletions src/pkg/cluster/cluster.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2021-Present The Zarf Authors

// Package cluster contains Zarf-specific cluster management functions.
package cluster

import (
"context"
"fmt"
"time"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"sigs.k8s.io/cli-utils/pkg/kstatus/watcher"

pkgkubernetes "github.com/defenseunicorns/pkg/kubernetes"

"github.com/defenseunicorns/zarf/src/pkg/message"
)

const (
// DefaultTimeout is the default time to wait for a cluster to be ready.
DefaultTimeout = 30 * time.Second
// AgentLabel is used to give instructions to the Zarf agent
AgentLabel = "zarf.dev/agent"
)

// Cluster Zarf specific cluster management functions.
type Cluster struct {
Clientset kubernetes.Interface
RestConfig *rest.Config
Watcher watcher.StatusWatcher
}

// NewClusterWithWait creates a new Cluster instance and waits for the given timeout for the cluster to be ready.
func NewClusterWithWait(ctx context.Context) (*Cluster, error) {
spinner := message.NewProgressSpinner("Waiting for cluster connection")
defer spinner.Stop()

c, err := NewCluster()
if err != nil {
return nil, err
}
err = waitForHealthyCluster(ctx, c.Clientset)
if err != nil {
return nil, err
}

spinner.Success()

return c, nil
}

// NewCluster creates a new Cluster instance and validates connection to the cluster by fetching the Kubernetes version.
func NewCluster() (*Cluster, error) {
clientset, config, err := pkgkubernetes.ClientAndConfig()
if err != nil {
return nil, err
}
watcher, err := pkgkubernetes.WatcherForConfig(config)
if err != nil {
return nil, err
}
c := &Cluster{
Clientset: clientset,
RestConfig: config,
Watcher: watcher,
}
// Dogsled the version output. We just want to ensure no errors were returned to validate cluster connection.
_, err = c.Clientset.Discovery().ServerVersion()
if err != nil {
return nil, err
}
return c, nil
}

// WaitForHealthyCluster checks for an available K8s cluster every second until timeout.
func waitForHealthyCluster(ctx context.Context, client kubernetes.Interface) error {
const waitDuration = 1 * time.Second

timer := time.NewTimer(0)
defer timer.Stop()

for {
select {
case <-ctx.Done():
return fmt.Errorf("error waiting for cluster to report healthy: %w", ctx.Err())
case <-timer.C:
// Make sure there is at least one running Node
nodeList, err := client.CoreV1().Nodes().List(ctx, metav1.ListOptions{})
if err != nil || len(nodeList.Items) < 1 {
message.Debug("No nodes reporting healthy yet: %v\n", err)
timer.Reset(waitDuration)
continue
}

// Get the cluster pod list
pods, err := client.CoreV1().Pods(corev1.NamespaceAll).List(ctx, metav1.ListOptions{})
if err != nil {
message.Debug("Could not get the pod list: %w", err)
timer.Reset(waitDuration)
continue
}

// Check that at least one pod is in the 'succeeded' or 'running' state
for _, pod := range pods.Items {
if pod.Status.Phase == corev1.PodSucceeded || pod.Status.Phase == corev1.PodRunning {
return nil
}
}

message.Debug("No pods reported 'succeeded' or 'running' state yet.")
timer.Reset(waitDuration)
}
}
}
65 changes: 0 additions & 65 deletions src/pkg/cluster/common.go

This file was deleted.

23 changes: 12 additions & 11 deletions src/pkg/cluster/injector.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,6 @@ import (
"regexp"
"time"

"github.com/defenseunicorns/pkg/helpers/v2"
pkgkubernetes "github.com/defenseunicorns/pkg/kubernetes"
"github.com/defenseunicorns/zarf/src/config"
"github.com/defenseunicorns/zarf/src/pkg/k8s"
"github.com/defenseunicorns/zarf/src/pkg/layout"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/transform"
"github.com/defenseunicorns/zarf/src/pkg/utils"
"github.com/google/go-containerregistry/pkg/crane"
"github.com/google/uuid"
"github.com/mholt/archiver/v3"
Expand All @@ -30,6 +22,15 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/intstr"
"sigs.k8s.io/cli-utils/pkg/object"

"github.com/defenseunicorns/pkg/helpers/v2"
pkgkubernetes "github.com/defenseunicorns/pkg/kubernetes"

"github.com/defenseunicorns/zarf/src/config"
"github.com/defenseunicorns/zarf/src/pkg/layout"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/transform"
"github.com/defenseunicorns/zarf/src/pkg/utils"
)

// The chunk size for the tarball chunks.
Expand Down Expand Up @@ -380,8 +381,8 @@ func (c *Cluster) buildInjectionPod(node, image string, payloadConfigmaps []stri
Name: fmt.Sprintf("injector-%s", uuid),
Namespace: ZarfNamespaceName,
Labels: map[string]string{
"app": "zarf-injector",
k8s.AgentLabel: "ignore",
"app": "zarf-injector",
AgentLabel: "ignore",
},
},
Spec: corev1.PodSpec{
Expand Down Expand Up @@ -544,7 +545,7 @@ func (c *Cluster) getImagesAndNodesForInjection(ctx context.Context) (imageNodeM
return result, nil
}

c.Log("No images found on any node. Retrying...")
message.Debug("No images found on any node. Retrying...")
timer.Reset(2 * time.Second)
}
}
Expand Down
15 changes: 3 additions & 12 deletions src/pkg/cluster/injector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"

"github.com/defenseunicorns/zarf/src/pkg/k8s"
)

func TestCreateInjectorConfigMap(t *testing.T) {
Expand All @@ -32,9 +30,7 @@ func TestCreateInjectorConfigMap(t *testing.T) {

cs := fake.NewSimpleClientset()
c := &Cluster{
&k8s.K8s{
Clientset: cs,
},
Clientset: cs,
}

ctx := context.Background()
Expand All @@ -52,9 +48,7 @@ func TestCreateService(t *testing.T) {

cs := fake.NewSimpleClientset()
c := &Cluster{
&k8s.K8s{
Clientset: cs,
},
Clientset: cs,
}

expected, err := os.ReadFile("./testdata/expected-injection-service.json")
Expand Down Expand Up @@ -94,10 +88,7 @@ func TestImagesAndNodesForInjection(t *testing.T) {
cs := fake.NewSimpleClientset()

c := &Cluster{
&k8s.K8s{
Clientset: cs,
Log: func(string, ...any) {},
},
Clientset: cs,
}

nodes := []corev1.Node{
Expand Down
6 changes: 3 additions & 3 deletions src/pkg/cluster/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ 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"

"github.com/defenseunicorns/zarf/src/pkg/message"
)

// DeleteZarfNamespace deletes the Zarf namespace from the connected cluster.
Expand Down Expand Up @@ -66,6 +66,6 @@ func AdoptZarfManagedLabels(labels map[string]string) map[string]string {
if labels == nil {
labels = make(map[string]string)
}
labels[k8s.ZarfManagedByLabel] = "zarf"
labels[ZarfManagedByLabel] = "zarf"
return labels
}
9 changes: 4 additions & 5 deletions src/pkg/cluster/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/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"
)
Expand Down Expand Up @@ -119,8 +118,8 @@ func (c *Cluster) UpdateZarfManagedImageSecrets(ctx context.Context, state *type
}

// Check if this is a Zarf managed secret or is in a namespace the Zarf agent will take action in
if currentRegistrySecret.Labels[k8s.ZarfManagedByLabel] == "zarf" ||
(namespace.Labels[k8s.AgentLabel] != "skip" && namespace.Labels[k8s.AgentLabel] != "ignore") {
if currentRegistrySecret.Labels[ZarfManagedByLabel] == "zarf" ||
(namespace.Labels[AgentLabel] != "skip" && namespace.Labels[AgentLabel] != "ignore") {
spinner.Updatef("Updating existing Zarf-managed image secret for namespace: '%s'", namespace.Name)

newRegistrySecret := c.GenerateRegistryPullCreds(namespace.Name, config.ZarfImagePullSecretName, state.RegistryInfo)
Expand Down Expand Up @@ -154,8 +153,8 @@ func (c *Cluster) UpdateZarfManagedGitSecrets(ctx context.Context, state *types.
}

// Check if this is a Zarf managed secret or is in a namespace the Zarf agent will take action in
if currentGitSecret.Labels[k8s.ZarfManagedByLabel] == "zarf" ||
(namespace.Labels[k8s.AgentLabel] != "skip" && namespace.Labels[k8s.AgentLabel] != "ignore") {
if currentGitSecret.Labels[ZarfManagedByLabel] == "zarf" ||
(namespace.Labels[AgentLabel] != "skip" && namespace.Labels[AgentLabel] != "ignore") {
spinner.Updatef("Updating existing Zarf-managed git secret for namespace: '%s'", namespace.Name)

// Create the secret
Expand Down
5 changes: 2 additions & 3 deletions src/pkg/cluster/secrets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/defenseunicorns/zarf/src/pkg/k8s"
"github.com/defenseunicorns/zarf/src/types"
)

Expand All @@ -33,7 +32,7 @@ func TestGenerateRegistryPullCreds(t *testing.T) {
Name: "bar",
Namespace: "foo",
Labels: map[string]string{
k8s.ZarfManagedByLabel: "zarf",
ZarfManagedByLabel: "zarf",
},
},
Type: corev1.SecretTypeDockerConfigJson,
Expand Down Expand Up @@ -62,7 +61,7 @@ func TestGenerateGitPullCreds(t *testing.T) {
Name: "bar",
Namespace: "foo",
Labels: map[string]string{
k8s.ZarfManagedByLabel: "zarf",
ZarfManagedByLabel: "zarf",
},
},
Type: corev1.SecretTypeOpaque,
Expand Down
Loading

0 comments on commit 1b104dc

Please sign in to comment.