Skip to content

Commit

Permalink
tests passing
Browse files Browse the repository at this point in the history
Signed-off-by: Austin Abro <[email protected]>
  • Loading branch information
AustinAbro321 committed Oct 17, 2024
1 parent 9f757e9 commit 0219569
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 160 deletions.
240 changes: 99 additions & 141 deletions src/pkg/cluster/injector.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/zarf-dev/zarf/src/pkg/message"
"github.com/zarf-dev/zarf/src/pkg/transform"
"github.com/zarf-dev/zarf/src/pkg/utils"
v1ac "k8s.io/client-go/applyconfigurations/core/v1"
)

// StartInjection initializes a Zarf injection into the cluster.
Expand All @@ -43,16 +44,15 @@ func (c *Cluster) StartInjection(ctx context.Context, tmpDir, imagesDir string,
spinner := message.NewProgressSpinner("Attempting to bootstrap the seed image into the cluster")
defer spinner.Stop()

resReq := corev1.ResourceRequirements{
Requests: corev1.ResourceList{
resReq := v1ac.ResourceRequirements().
WithRequests(corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse(".5"),
corev1.ResourceMemory: resource.MustParse("64Mi"),
},
Limits: corev1.ResourceList{
}).
WithLimits(corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("1"),
corev1.ResourceMemory: resource.MustParse("256Mi"),
},
}
})
injectorImage, injectorNodeName, err := c.getInjectorImageAndNode(ctx, resReq)
if err != nil {
return err
Expand All @@ -67,50 +67,32 @@ func (c *Cluster) StartInjection(ctx context.Context, tmpDir, imagesDir string,
if err != nil {
return err
}
cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: ZarfNamespaceName,
Name: "rust-binary",
},
BinaryData: map[string][]byte{
cm := v1ac.ConfigMap("rust-binary", ZarfNamespaceName).
WithBinaryData(map[string][]byte{
"zarf-injector": b,
},
}
_, err = c.Clientset.CoreV1().ConfigMaps(cm.Namespace).Create(ctx, cm, metav1.CreateOptions{})
})
_, err = c.Clientset.CoreV1().ConfigMaps(*cm.Namespace).Apply(ctx, cm, metav1.ApplyOptions{Force: true, FieldManager: "zarf"})
if err != nil {
return err
}

svc := &corev1.Service{
TypeMeta: metav1.TypeMeta{
APIVersion: corev1.SchemeGroupVersion.String(),
Kind: "Service",
},
ObjectMeta: metav1.ObjectMeta{
Namespace: ZarfNamespaceName,
Name: "zarf-injector",
},
Spec: corev1.ServiceSpec{
Type: corev1.ServiceTypeNodePort,
Ports: []corev1.ServicePort{
{
Port: int32(5000),
},
},
Selector: map[string]string{
"app": "zarf-injector",
},
},
}
svc, err = c.Clientset.CoreV1().Services(svc.Namespace).Create(ctx, svc, metav1.CreateOptions{})
svc := v1ac.Service("zarf-injector", ZarfNamespaceName).
WithSpec(v1ac.ServiceSpec().
WithType(corev1.ServiceTypeNodePort).
WithPorts(
v1ac.ServicePort().WithPort(int32(5000)),
).WithSelector(map[string]string{
"app": "zarf-injector",
}))
_, err = c.Clientset.CoreV1().Services(*svc.Namespace).Apply(ctx, svc, metav1.ApplyOptions{Force: true, FieldManager: "zarf"})
if err != nil {
return err
}
// TODO: Remove use of passing data through global variables.
config.ZarfSeedPort = fmt.Sprintf("%d", svc.Spec.Ports[0].NodePort)

pod := buildInjectionPod(injectorNodeName, injectorImage, payloadCmNames, shasum, resReq)
_, err = c.Clientset.CoreV1().Pods(pod.Namespace).Create(ctx, pod, metav1.CreateOptions{})
podAc := buildInjectionPod(injectorNodeName, injectorImage, payloadCmNames, shasum, resReq)
pod, err := c.Clientset.CoreV1().Pods(*podAc.Namespace).Apply(ctx, podAc, metav1.ApplyOptions{Force: true, FieldManager: "zarf"})
if err != nil {
return fmt.Errorf("error creating pod in cluster: %w", err)
}
Expand Down Expand Up @@ -236,19 +218,14 @@ func (c *Cluster) createPayloadConfigMaps(ctx context.Context, spinner *message.

spinner.Updatef("Adding archive binary configmap %d of %d to the cluster", i+1, len(chunks))

cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: ZarfNamespaceName,
Name: fileName,
Labels: map[string]string{
"zarf-injector": "payload",
},
},
BinaryData: map[string][]byte{
cm := v1ac.ConfigMap(fileName, ZarfNamespaceName).
WithLabels(map[string]string{
"zarf-injector": "payload",
}).
WithBinaryData(map[string][]byte{
fileName: data,
},
}
_, err = c.Clientset.CoreV1().ConfigMaps(ZarfNamespaceName).Create(ctx, cm, metav1.CreateOptions{})
})
_, err = c.Clientset.CoreV1().ConfigMaps(ZarfNamespaceName).Apply(ctx, cm, metav1.ApplyOptions{Force: true, FieldManager: "zarf"})
if err != nil {
return nil, "", err
}
Expand All @@ -261,7 +238,7 @@ func (c *Cluster) createPayloadConfigMaps(ctx context.Context, spinner *message.
}

// getImagesAndNodesForInjection checks for images on schedulable nodes within a cluster.
func (c *Cluster) getInjectorImageAndNode(ctx context.Context, resReq corev1.ResourceRequirements) (string, string, error) {
func (c *Cluster) getInjectorImageAndNode(ctx context.Context, resReq *v1ac.ResourceRequirementsApplyConfiguration) (string, string, error) {
// Regex for Zarf seed image
zarfImageRegex, err := regexp.Compile(`(?m)^127\.0\.0\.1:`)
if err != nil {
Expand All @@ -279,8 +256,8 @@ func (c *Cluster) getInjectorImageAndNode(ctx context.Context, resReq corev1.Res
if err != nil {
return "", "", err
}
if nodeDetails.Status.Allocatable.Cpu().Cmp(resReq.Requests[corev1.ResourceCPU]) < 0 ||
nodeDetails.Status.Allocatable.Memory().Cmp(resReq.Requests[corev1.ResourceMemory]) < 0 {
if nodeDetails.Status.Allocatable.Cpu().Cmp(*resReq.Requests.Cpu()) < 0 ||
nodeDetails.Status.Allocatable.Memory().Cmp(*resReq.Requests.Memory()) < 0 {
continue
}
if hasBlockingTaints(nodeDetails.Spec.Taints) {
Expand Down Expand Up @@ -317,99 +294,80 @@ func hasBlockingTaints(taints []corev1.Taint) bool {
return false
}

func buildInjectionPod(nodeName, image string, payloadCmNames []string, shasum string, resReq corev1.ResourceRequirements) *corev1.Pod {
func buildInjectionPod(nodeName, image string, payloadCmNames []string, shasum string, resReq *v1ac.ResourceRequirementsApplyConfiguration) *v1ac.PodApplyConfiguration {
// Initialize base volumes
executeMode := int32(0777)
volumes := []*v1ac.VolumeApplyConfiguration{
v1ac.Volume().
WithName("init").
WithConfigMap(
v1ac.ConfigMapVolumeSource().
WithName("rust-binary").
WithDefaultMode(executeMode),
),
v1ac.Volume().
WithName("seed").
WithEmptyDir(&v1ac.EmptyDirVolumeSourceApplyConfiguration{}),
}

pod := &corev1.Pod{
TypeMeta: metav1.TypeMeta{
APIVersion: corev1.SchemeGroupVersion.String(),
Kind: "Pod",
},
ObjectMeta: metav1.ObjectMeta{
Name: "injector",
Namespace: ZarfNamespaceName,
Labels: map[string]string{
"app": "zarf-injector",
AgentLabel: "ignore",
},
},
Spec: corev1.PodSpec{
NodeName: nodeName,
// Do not try to restart the pod as it will be deleted/re-created instead.
RestartPolicy: corev1.RestartPolicyNever,
Containers: []corev1.Container{
{
Name: "injector",
Image: image,
ImagePullPolicy: corev1.PullIfNotPresent,
WorkingDir: "/zarf-init",
Command: []string{"/zarf-init/zarf-injector", shasum},
VolumeMounts: []corev1.VolumeMount{
{
Name: "init",
MountPath: "/zarf-init/zarf-injector",
SubPath: "zarf-injector",
},
{
Name: "seed",
MountPath: "/zarf-seed",
},
},
ReadinessProbe: &corev1.Probe{
PeriodSeconds: 2,
SuccessThreshold: 1,
FailureThreshold: 10,
ProbeHandler: corev1.ProbeHandler{
HTTPGet: &corev1.HTTPGetAction{
Path: "/v2/",
Port: intstr.FromInt(5000),
},
},
},
Resources: resReq,
},
},
Volumes: []corev1.Volume{
// Contains the rust binary and collection of configmaps from the tarball (seed image).
{
Name: "init",
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: "rust-binary",
},
DefaultMode: &executeMode,
},
},
},
// Empty directory to hold the seed image (new dir to avoid permission issues)
{
Name: "seed",
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
},
},
},
// Initialize base volume mounts
volumeMounts := []*v1ac.VolumeMountApplyConfiguration{
v1ac.VolumeMount().
WithName("init").
WithMountPath("/zarf-init/zarf-injector").
WithSubPath("zarf-injector"),
v1ac.VolumeMount().
WithName("seed").
WithMountPath("/zarf-seed"),
}

// Add additional volumes and volume mounts from payloadCmNames
for _, filename := range payloadCmNames {
pod.Spec.Volumes = append(pod.Spec.Volumes, corev1.Volume{
Name: filename,
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: filename,
},
},
},
})
pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
Name: filename,
MountPath: fmt.Sprintf("/zarf-init/%s", filename),
SubPath: filename,
})
volumes = append(volumes, v1ac.Volume().
WithName(filename).
WithConfigMap(
v1ac.ConfigMapVolumeSource().
WithName(filename),
))
volumeMounts = append(volumeMounts, v1ac.VolumeMount().
WithName(filename).
WithMountPath(fmt.Sprintf("/zarf-init/%s", filename)).
WithSubPath(filename))
}

// Construct the PodApplyConfiguration
pod := v1ac.Pod("injector", ZarfNamespaceName).
WithLabels(map[string]string{
"app": "zarf-injector",
AgentLabel: "ignore",
}).
WithSpec(
v1ac.PodSpec().
WithNodeName(nodeName).
WithRestartPolicy(corev1.RestartPolicyNever).
WithContainers(
v1ac.Container().
WithName("injector").
WithImage(image).
WithImagePullPolicy(corev1.PullIfNotPresent).
WithWorkingDir("/zarf-init").
WithCommand("/zarf-init/zarf-injector", shasum).
WithVolumeMounts(volumeMounts...).
WithReadinessProbe(
v1ac.Probe().
WithPeriodSeconds(2).
WithSuccessThreshold(1).
WithFailureThreshold(10).
WithHTTPGet(
v1ac.HTTPGetAction().
WithPath("/v2/").
WithPort(intstr.FromInt(5000)),
),
).
WithResources(resReq),
).
WithVolumes(volumes...),
)

return pod
}
40 changes: 22 additions & 18 deletions src/pkg/cluster/injector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
v1ac "k8s.io/client-go/applyconfigurations/core/v1"
"k8s.io/client-go/kubernetes/fake"
k8stesting "k8s.io/client-go/testing"
"sigs.k8s.io/cli-utils/pkg/kstatus/status"
)

func TestInjector(t *testing.T) {
ctx := context.Background()
cs := fake.NewSimpleClientset()
cs := fake.NewClientset()
c := &Cluster{
Clientset: cs,
Watcher: healthchecks.NewImmediateWatcher(status.CurrentStatus),
Expand Down Expand Up @@ -117,6 +118,8 @@ func TestInjector(t *testing.T) {
expected, err := os.ReadFile("./testdata/expected-injection-service.json")
require.NoError(t, err)
svc, err := cs.CoreV1().Services(ZarfNamespaceName).Get(ctx, "zarf-injector", metav1.GetOptions{})
// Managed fields are auto-set and contain timestamps
svc.ManagedFields = nil
require.NoError(t, err)
b, err := json.Marshal(svc)
require.NoError(t, err)
Expand Down Expand Up @@ -147,20 +150,21 @@ func TestInjector(t *testing.T) {
func TestBuildInjectionPod(t *testing.T) {
t.Parallel()

resReq := corev1.ResourceRequirements{
Requests: corev1.ResourceList{
resReq := v1ac.ResourceRequirements().
WithRequests(corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse(".5"),
corev1.ResourceMemory: resource.MustParse("64Mi"),
},
Limits: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("1"),
corev1.ResourceMemory: resource.MustParse("256Mi"),
},
}
}).
WithLimits(
corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("1"),
corev1.ResourceMemory: resource.MustParse("256Mi"),
})
pod := buildInjectionPod("injection-node", "docker.io/library/ubuntu:latest", []string{"foo", "bar"}, "shasum", resReq)
require.Equal(t, "injector", pod.Name)
require.Equal(t, "injector", *pod.Name)
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))
Expand Down Expand Up @@ -270,16 +274,16 @@ func TestGetInjectorImageAndNode(t *testing.T) {
require.NoError(t, err)
}

resReq := corev1.ResourceRequirements{
Requests: corev1.ResourceList{
resReq := v1ac.ResourceRequirements().
WithRequests(corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse(".5"),
corev1.ResourceMemory: resource.MustParse("64Mi"),
},
Limits: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("1"),
corev1.ResourceMemory: resource.MustParse("256Mi"),
},
}
}).
WithLimits(
corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("1"),
corev1.ResourceMemory: resource.MustParse("256Mi"),
})
image, node, err := c.getInjectorImageAndNode(ctx, resReq)
require.NoError(t, err)
require.Equal(t, "pod-2-container", image)
Expand Down
2 changes: 1 addition & 1 deletion src/pkg/cluster/testdata/expected-injection-pod.json
Original file line number Diff line number Diff line change
@@ -1 +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":{}}
{"kind":"Pod","apiVersion":"v1","metadata":{"name":"injector","namespace":"zarf","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"}}

0 comments on commit 0219569

Please sign in to comment.