Skip to content

Commit

Permalink
test: zarf init state
Browse files Browse the repository at this point in the history
  • Loading branch information
phillebaba committed May 30, 2024
1 parent 9da7406 commit 009cbd6
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 3 deletions.
25 changes: 23 additions & 2 deletions src/pkg/cluster/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ func (c *Cluster) InitZarfState(ctx context.Context, initOptions types.ZarfInitO
if err != nil {
return err
}
if len(nodeList.Items) == 0 {
return fmt.Errorf("cannot init Zarf state in empty cluster")
}
namespaceList, err := c.Clientset.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
if err != nil {
return err
Expand All @@ -90,6 +93,10 @@ func (c *Cluster) InitZarfState(ctx context.Context, initOptions types.ZarfInitO
}
// 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
}
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 @@ -107,8 +114,22 @@ func (c *Cluster) InitZarfState(ctx context.Context, initOptions types.ZarfInitO
// Try to create the zarf namespace.
spinner.Updatef("Creating the Zarf namespace")
zarfNamespace := NewZarfManagedNamespace(ZarfNamespaceName)
if _, err := c.CreateNamespace(ctx, zarfNamespace); err != nil {
return fmt.Errorf("unable to create the zarf namespace: %w", err)
err = func() error {
_, err := c.Clientset.CoreV1().Namespaces().Create(ctx, zarfNamespace, metav1.CreateOptions{})
if err != nil && !kerrors.IsAlreadyExists(err) {
return fmt.Errorf("unable to create the Zarf namespace: %w", err)
}
if err == nil {
return nil
}
_, err = c.Clientset.CoreV1().Namespaces().Update(ctx, zarfNamespace, metav1.UpdateOptions{})
if err != nil {
return fmt.Errorf("unable to update the Zarf namespace: %w", err)
}
return nil
}()
if err != nil {
return err
}

// Wait up to 2 minutes for the default service account to be created.
Expand Down
165 changes: 164 additions & 1 deletion src/pkg/cluster/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,179 @@
package cluster

import (
"context"
"fmt"
"testing"
"time"

"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"

"github.com/defenseunicorns/pkg/helpers"

"github.com/defenseunicorns/zarf/src/pkg/k8s"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/pki"
"github.com/defenseunicorns/zarf/src/types"
"github.com/stretchr/testify/require"
)

func TestInitZarfState(t *testing.T) {
tests := []struct {
name string
initOpts types.ZarfInitOptions
nodes []corev1.Node
namespaces []corev1.Namespace
secrets []corev1.Secret
expectedErr string
}{
{
name: "no nodes in cluster",
expectedErr: "cannot init Zarf state in empty cluster",
},
{
name: "no namespaces exist",
initOpts: types.ZarfInitOptions{},
nodes: []corev1.Node{
{
ObjectMeta: metav1.ObjectMeta{
Name: "node",
},
},
},
},
{
name: "namespaces exists",
nodes: []corev1.Node{
{
ObjectMeta: metav1.ObjectMeta{
Name: "node",
},
},
},
namespaces: []corev1.Namespace{
{
ObjectMeta: metav1.ObjectMeta{
Name: "kube-system",
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
},
},
},
},
{
name: "Zarf namespace exists",
nodes: []corev1.Node{
{
ObjectMeta: metav1.ObjectMeta{
Name: "node",
},
},
},
namespaces: []corev1.Namespace{
{
ObjectMeta: metav1.ObjectMeta{
Name: ZarfNamespaceName,
},
},
},
},
{
name: "Zarf state exists",
nodes: []corev1.Node{
{
ObjectMeta: metav1.ObjectMeta{
Name: "node",
},
},
},
namespaces: []corev1.Namespace{
{
ObjectMeta: metav1.ObjectMeta{
Name: ZarfNamespaceName,
},
},
},
secrets: []corev1.Secret{
{
ObjectMeta: metav1.ObjectMeta{
Namespace: ZarfNamespaceName,
Name: ZarfStateSecretName,
},
},
},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
cs := fake.NewSimpleClientset()
for _, node := range tt.nodes {
_, err := cs.CoreV1().Nodes().Create(ctx, &node, metav1.CreateOptions{})
require.NoError(t, err)
}
for _, namespace := range tt.namespaces {
_, err := cs.CoreV1().Namespaces().Create(ctx, &namespace, metav1.CreateOptions{})
require.NoError(t, err)
}
for _, secret := range tt.secrets {
_, err := cs.CoreV1().Secrets(secret.ObjectMeta.Namespace).Create(ctx, &secret, metav1.CreateOptions{})
require.NoError(t, err)
}
c := &Cluster{
&k8s.K8s{
Clientset: cs,
Log: func(string, ...any) {},
},
}

// Create default service account in Zarf namespace
go func() {
for {
time.Sleep(1 * time.Second)
ns, err := cs.CoreV1().Namespaces().Get(ctx, ZarfNamespaceName, metav1.GetOptions{})
if err != nil {
continue
}
sa := &corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Namespace: ns.Name,
Name: "default",
},
}
cs.CoreV1().ServiceAccounts(ns.Name).Create(ctx, sa, metav1.CreateOptions{})
break
}
}()

err := c.InitZarfState(ctx, tt.initOpts)
if tt.expectedErr != "" {
require.EqualError(t, err, tt.expectedErr)
return
}
require.NoError(t, err)
zarfNs, err := cs.CoreV1().Namespaces().Get(ctx, ZarfNamespaceName, metav1.GetOptions{})
require.NoError(t, err)
require.Equal(t, map[string]string{"app.kubernetes.io/managed-by": "zarf"}, zarfNs.Labels)
_, err = cs.CoreV1().Secrets(zarfNs.Name).Get(ctx, ZarfStateSecretName, metav1.GetOptions{})
require.NoError(t, err)
for _, ns := range tt.namespaces {
if ns.Name == zarfNs.Name {
continue
}
ns, err := cs.CoreV1().Namespaces().Get(ctx, ns.Name, metav1.GetOptions{})
require.NoError(t, err)
require.Equal(t, map[string]string{k8s.AgentLabel: "ignore"}, ns.Labels)
}
})
}
}

// TODO: Change password gen method to make testing possible.
func TestMergeZarfStateRegistry(t *testing.T) {
t.Parallel()
Expand Down

0 comments on commit 009cbd6

Please sign in to comment.