Skip to content

Commit

Permalink
test: add tests for injector (#2534)
Browse files Browse the repository at this point in the history
## Description

Adds tests to injector.

## Related Issue

Relates to #2512 

## 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
  • Loading branch information
phillebaba authored May 22, 2024
1 parent 04e1c78 commit 3c77d11
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 8 deletions.
23 changes: 15 additions & 8 deletions src/pkg/cluster/injector.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func (c *Cluster) StartInjectionMadness(ctx context.Context, tmpDir string, imag
}

spinner.Updatef("Creating the injector configmap")
if err = c.createInjectorConfigmap(ctx, tmp.InjectionBinary); err != nil {
if err = c.createInjectorConfigMap(ctx, tmp.InjectionBinary); err != nil {
spinner.Fatalf(err, "Unable to create the injector configmap")
}

Expand All @@ -90,7 +90,7 @@ func (c *Cluster) StartInjectionMadness(ctx context.Context, tmpDir string, imag
}

spinner.Updatef("Loading the seed registry configmaps")
if payloadConfigmaps, sha256sum, err = c.createPayloadConfigmaps(ctx, tmp.SeedImagesDir, tmp.InjectorPayloadTarGz, spinner); err != nil {
if payloadConfigmaps, sha256sum, err = c.createPayloadConfigMaps(ctx, tmp.SeedImagesDir, tmp.InjectorPayloadTarGz, spinner); err != nil {
spinner.Fatalf(err, "Unable to generate the injector payload configmaps")
}

Expand Down Expand Up @@ -197,7 +197,7 @@ func (c *Cluster) loadSeedImages(imagesDir, seedImagesDir string, injectorSeedSr
return seedImages, nil
}

func (c *Cluster) createPayloadConfigmaps(ctx context.Context, seedImagesDir, tarPath string, spinner *message.Spinner) ([]string, string, error) {
func (c *Cluster) createPayloadConfigMaps(ctx context.Context, seedImagesDir, tarPath string, spinner *message.Spinner) ([]string, string, error) {
var configMaps []string

// Chunk size has to accommodate base64 encoding & etcd 1MB limit
Expand Down Expand Up @@ -285,7 +285,7 @@ func (c *Cluster) injectorIsReady(ctx context.Context, seedImages []transform.Im
return true
}

func (c *Cluster) createInjectorConfigmap(ctx context.Context, binaryPath string) error {
func (c *Cluster) createInjectorConfigMap(ctx context.Context, binaryPath string) error {
var err error
configData := make(map[string][]byte)

Expand Down Expand Up @@ -473,10 +473,8 @@ func (c *Cluster) getImagesAndNodesForInjection(ctx context.Context) (imageNodeM
continue
}

for _, taint := range nodeDetails.Spec.Taints {
if taint.Effect == corev1.TaintEffectNoSchedule || taint.Effect == corev1.TaintEffectNoExecute {
continue
}
if hasBlockingTaints(nodeDetails.Spec.Taints) {
continue
}

for _, container := range pod.Spec.InitContainers {
Expand All @@ -499,3 +497,12 @@ func (c *Cluster) getImagesAndNodesForInjection(ctx context.Context) (imageNodeM
}
}
}

func hasBlockingTaints(taints []corev1.Taint) bool {
for _, taint := range taints {
if taint.Effect == corev1.TaintEffectNoSchedule || taint.Effect == corev1.TaintEffectNoExecute {
return true
}
}
return false
}
204 changes: 204 additions & 0 deletions src/pkg/cluster/injector_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2021-Present The Zarf Authors

package cluster

import (
"context"
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"testing"
"time"

"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
"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) {
t.Parallel()

binData := []byte("foobar")
binPath := filepath.Join(t.TempDir(), "bin")
err := os.WriteFile(binPath, binData, 0o644)
require.NoError(t, err)

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

ctx := context.Background()
for i := 0; i < 2; i++ {
err = c.createInjectorConfigMap(ctx, binPath)
require.NoError(t, err)
cm, err := cs.CoreV1().ConfigMaps(ZarfNamespaceName).Get(ctx, "rust-binary", metav1.GetOptions{})
require.NoError(t, err)
require.Equal(t, binData, cm.BinaryData["zarf-injector"])
}
}

func TestCreateService(t *testing.T) {
t.Parallel()

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

expected, err := os.ReadFile("./testdata/expected-injection-service.json")
require.NoError(t, err)
ctx := context.Background()
for i := 0; i < 2; i++ {
_, err := c.createService(ctx)
require.NoError(t, err)
svc, err := cs.CoreV1().Services(ZarfNamespaceName).Get(ctx, "zarf-injector", metav1.GetOptions{})
require.NoError(t, err)
b, err := json.Marshal(svc)
require.NoError(t, err)
require.Equal(t, strings.TrimSpace(string(expected)), string(b))
}
}

func TestBuildInjectionPod(t *testing.T) {
t.Parallel()

c := &Cluster{}
pod, err := c.buildInjectionPod("injection-node", "docker.io/library/ubuntu:latest", []string{"foo", "bar"}, "shasum")
require.NoError(t, err)
b, err := json.Marshal(pod)
require.NoError(t, err)
expected, err := os.ReadFile("./testdata/expected-injection-pod.json")
require.NoError(t, err)
require.Equal(t, strings.TrimSpace(string(expected)), string(b))
}

func TestImagesAndNodesForInjection(t *testing.T) {
t.Parallel()

ctx := context.Background()
cs := fake.NewSimpleClientset()

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

nodes := []corev1.Node{
{
ObjectMeta: metav1.ObjectMeta{
Name: "no-resources",
},
Status: corev1.NodeStatus{
Allocatable: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("400m"),
corev1.ResourceMemory: resource.MustParse("50Mi"),
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "no-schedule-taint",
},
Spec: corev1.NodeSpec{
Taints: []corev1.Taint{
{
Effect: corev1.TaintEffectNoSchedule,
},
},
},
Status: corev1.NodeStatus{
Allocatable: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("1000m"),
corev1.ResourceMemory: resource.MustParse("10Gi"),
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "good",
},
Status: corev1.NodeStatus{
Allocatable: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("1000m"),
corev1.ResourceMemory: resource.MustParse("10Gi"),
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "no-execute-taint",
},
Spec: corev1.NodeSpec{
Taints: []corev1.Taint{
{
Effect: corev1.TaintEffectNoExecute,
},
},
},
Status: corev1.NodeStatus{
Allocatable: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("1000m"),
corev1.ResourceMemory: resource.MustParse("10Gi"),
},
},
},
}
for i, node := range nodes {
_, err := cs.CoreV1().Nodes().Create(ctx, &node, metav1.CreateOptions{})
require.NoError(t, err)
podName := fmt.Sprintf("pod-%d", i)
pod := corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: podName,
Namespace: "default",
},
Spec: corev1.PodSpec{
NodeName: node.ObjectMeta.Name,
InitContainers: []corev1.Container{
{
Image: podName + "-init",
},
},
Containers: []corev1.Container{
{
Image: podName + "-container",
},
},
EphemeralContainers: []corev1.EphemeralContainer{
{
EphemeralContainerCommon: corev1.EphemeralContainerCommon{
Image: podName + "-ephemeral",
},
},
},
},
}
_, err = cs.CoreV1().Pods(pod.Namespace).Create(ctx, &pod, metav1.CreateOptions{})
require.NoError(t, err)
}

getCtx, getCancel := context.WithTimeout(ctx, 1*time.Second)
defer getCancel()
result, err := c.getImagesAndNodesForInjection(getCtx)
require.NoError(t, err)
expected := imageNodeMap{
"pod-2-init": []string{"good"},
"pod-2-container": []string{"good"},
"pod-2-ephemeral": []string{"good"},
}
require.Equal(t, expected, result)
}
1 change: 1 addition & 0 deletions src/pkg/cluster/testdata/expected-injection-pod.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"kind":"Pod","apiVersion":"v1","metadata":{"name":"injector","namespace":"zarf","creationTimestamp":null,"labels":{"app":"zarf-injector","zarf.dev/agent":"ignore"}},"spec":{"volumes":[{"name":"init","configMap":{"name":"rust-binary","defaultMode":511}},{"name":"seed","emptyDir":{}},{"name":"foo","configMap":{"name":"foo"}},{"name":"bar","configMap":{"name":"bar"}}],"containers":[{"name":"injector","image":"docker.io/library/ubuntu:latest","command":["/zarf-init/zarf-injector","shasum"],"workingDir":"/zarf-init","resources":{"limits":{"cpu":"1","memory":"256Mi"},"requests":{"cpu":"500m","memory":"64Mi"}},"volumeMounts":[{"name":"init","mountPath":"/zarf-init/zarf-injector","subPath":"zarf-injector"},{"name":"seed","mountPath":"/zarf-seed"},{"name":"foo","mountPath":"/zarf-init/foo","subPath":"foo"},{"name":"bar","mountPath":"/zarf-init/bar","subPath":"bar"}],"readinessProbe":{"httpGet":{"path":"/v2/","port":5000},"periodSeconds":2,"successThreshold":1,"failureThreshold":10},"imagePullPolicy":"IfNotPresent"}],"restartPolicy":"Never","nodeName":"injection-node"},"status":{}}
1 change: 1 addition & 0 deletions src/pkg/cluster/testdata/expected-injection-service.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"kind":"Service","apiVersion":"v1","metadata":{"name":"zarf-injector","namespace":"zarf","creationTimestamp":null},"spec":{"ports":[{"port":5000,"targetPort":0}],"selector":{"app":"zarf-injector"},"type":"NodePort"},"status":{"loadBalancer":{}}}

0 comments on commit 3c77d11

Please sign in to comment.