Skip to content

Commit b5f89b1

Browse files
committed
feat: update injector to use Opt Struct
Signed-off-by: Allen Conlon <[email protected]>
1 parent 74fb033 commit b5f89b1

File tree

5 files changed

+235
-32
lines changed

5 files changed

+235
-32
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
name: Test multi-arch EKS Cluster
2+
on:
3+
schedule:
4+
- cron: "0 7 * * *" ## Every day at 0700 UTC
5+
workflow_dispatch: ## Give us the ability to run this manually
6+
# pull_request:
7+
8+
permissions:
9+
id-token: write
10+
contents: read
11+
12+
# Abort prior jobs in the same workflow / PR
13+
concurrency:
14+
group: e2e-eks-multi-arch-${{ github.ref }}
15+
cancel-in-progress: true
16+
17+
jobs:
18+
eks-nightly-test:
19+
if: ${{ github.repository == 'zarf-dev/zarf' }}
20+
runs-on: ubuntu-latest
21+
steps:
22+
- name: Checkout
23+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
24+
25+
- name: Setup golang
26+
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
27+
with:
28+
go-version-file: go.mod
29+
30+
- name: Build binary and zarf packages
31+
uses: ./.github/actions/packages
32+
33+
- name: Auth with AWS
34+
uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1
35+
with:
36+
role-to-assume: ${{ secrets.AWS_NIGHTLY_EKS_ROLE_ARN }}
37+
role-session-name: ${{ github.job || github.event.client_payload.pull_request.head.sha || github.sha }}
38+
aws-region: us-east-1
39+
role-duration-seconds: 7200
40+
41+
- name: Download eksctl
42+
run: |
43+
curl -L -o eksctl_Linux_amd64.tar.gz \
44+
https://github.com/weaveworks/eksctl/releases/download/v0.170.0/eksctl_Linux_amd64.tar.gz
45+
tar -xzf eksctl_Linux_amd64.tar.gz
46+
chmod +x eksctl
47+
48+
- name: Create EKS config
49+
run: |
50+
cat <<EOF > eks.yaml
51+
apiVersion: eksctl.io/v1alpha5
52+
kind: ClusterConfig
53+
metadata:
54+
name: zarf-nightly-multi-arch-e2e-test
55+
region: us-east-1
56+
tags:
57+
PermissionsBoundary: uds_permissions_boundary
58+
59+
iam:
60+
serviceRolePermissionsBoundary: arn:aws:iam::205930641482:policy/uds_permissions_boundary
61+
withOIDC: true
62+
63+
addons:
64+
- name: aws-ebs-csi-driver
65+
attachPolicyARNs:
66+
- arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy
67+
permissionsBoundary: "arn:aws:iam::205930641482:policy/uds_permissions_boundary"
68+
tags:
69+
PermissionsBoundary: "uds_permissions_boundary"
70+
71+
- name: vpc-cni
72+
attachPolicyARNs:
73+
- arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
74+
permissionsBoundary: "arn:aws:iam::205930641482:policy/uds_permissions_boundary"
75+
tags:
76+
PermissionsBoundary: "uds_permissions_boundary"
77+
78+
managedNodeGroups:
79+
- instanceType: t3.medium
80+
name: amd64-ng
81+
minSize: 2
82+
maxSize: 2
83+
spot: true
84+
tags:
85+
PermissionsBoundary: "uds_permissions_boundary"
86+
iam:
87+
instanceRolePermissionsBoundary: "arn:aws:iam::205930641482:policy/uds_permissions_boundary"
88+
- instanceType: "t4g.small"
89+
name: arm64-ng
90+
minSize: 2
91+
maxSize: 2
92+
spot: true
93+
tags:
94+
PermissionsBoundary: "uds_permissions_boundary"
95+
iam:
96+
instanceRolePermissionsBoundary: "arn:aws:iam::205930641482:policy/uds_permissions_boundary"
97+
EOF
98+
99+
- name: create cluster
100+
run: |
101+
./eksctl create cluster --dry-run --config-file eks.yaml
102+
./eksctl create cluster --config-file=eks.yaml
103+
104+
- name: init Zarf
105+
run: |
106+
./build/zarf init --confirm
107+
108+
- name: teardown cluster
109+
run: |
110+
./eksctl delete cluster --config-file=eks.yaml --disable-nodegroup-eviction --wait
111+
112+
- name: Send trigger to Slack on workflow failure
113+
if: failure()
114+
uses: ./.github/actions/slack
115+
with:
116+
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}

src/pkg/cluster/injector.go

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,23 @@ import (
3939

4040
var zarfImageRegex = regexp.MustCompile(`(?m)^(127\.0\.0\.1|\[::1\]):`)
4141

42+
// InjectorOpts represents the config for the injector pod
43+
type InjectorOpts struct {
44+
ImagesDir string
45+
InjectorSeedSrcs []string
46+
InjectorNodePort int
47+
RegistryNodePort int
48+
PkgName string
49+
Architecture string
50+
}
51+
4252
// StartInjection initializes a Zarf injection into the cluster
43-
func (c *Cluster) StartInjection(ctx context.Context, tmpDir, imagesDir string, injectorSeedSrcs []string, injectorNodePort int, registryNodePort int, pkgName string) (int, error) {
53+
func (c *Cluster) StartInjection(ctx context.Context, tmpDir string, opts InjectorOpts) (int, error) {
4454
l := logger.From(ctx)
4555
start := time.Now()
4656

4757
// The injector breaks if the same image is added multiple times
48-
injectorSeedSrcs = helpers.Unique(injectorSeedSrcs)
58+
opts.InjectorSeedSrcs = helpers.Unique(opts.InjectorSeedSrcs)
4959

5060
// Stop any previous running injection before starting.
5161
err := c.StopInjection(ctx)
@@ -55,12 +65,12 @@ func (c *Cluster) StartInjection(ctx context.Context, tmpDir, imagesDir string,
5565

5666
l.Info("creating Zarf injector resources")
5767

58-
svc, err := c.createInjectorNodeportService(ctx, injectorNodePort, registryNodePort, pkgName)
68+
svc, err := c.createInjectorNodeportService(ctx, opts)
5969
if err != nil {
6070
return 0, err
6171
}
6272

63-
payloadCmNames, shasum, err := c.CreateInjectorConfigMaps(ctx, tmpDir, imagesDir, injectorSeedSrcs, pkgName)
73+
payloadCmNames, shasum, err := c.CreateInjectorConfigMaps(ctx, tmpDir, opts)
6474
if err != nil {
6575
return 0, err
6676
}
@@ -74,12 +84,12 @@ func (c *Cluster) StartInjection(ctx context.Context, tmpDir, imagesDir string,
7484
corev1.ResourceCPU: resource.MustParse("1"),
7585
corev1.ResourceMemory: resource.MustParse("256Mi"),
7686
})
77-
injectorImage, injectorNodeName, err := c.getInjectorImageAndNode(ctx, resReq)
87+
injectorImage, injectorNodeName, err := c.getInjectorImageAndNode(ctx, resReq, opts)
7888
if err != nil {
7989
return 0, err
8090
}
8191

82-
pod := buildInjectionPod(injectorNodeName, injectorImage, payloadCmNames, shasum, resReq, pkgName)
92+
pod := buildInjectionPod(injectorNodeName, injectorImage, payloadCmNames, shasum, resReq, opts)
8393
_, err = c.Clientset.CoreV1().Pods(*pod.Namespace).Apply(ctx, pod, metav1.ApplyOptions{Force: true, FieldManager: FieldManagerName})
8494
if err != nil {
8595
return 0, fmt.Errorf("error creating pod in cluster: %w", err)
@@ -103,8 +113,8 @@ func (c *Cluster) StartInjection(ctx context.Context, tmpDir, imagesDir string,
103113
}
104114

105115
// CreateInjectorConfigMaps creates the required configmaps to run the injector
106-
func (c *Cluster) CreateInjectorConfigMaps(ctx context.Context, tmpDir, imagesDir string, injectorSeedSrcs []string, pkgName string) ([]string, string, error) {
107-
payloadCmNames, shasum, err := c.createPayloadConfigMaps(ctx, tmpDir, imagesDir, injectorSeedSrcs, pkgName)
116+
func (c *Cluster) CreateInjectorConfigMaps(ctx context.Context, tmpDir string, opts InjectorOpts) ([]string, string, error) {
117+
payloadCmNames, shasum, err := c.createPayloadConfigMaps(ctx, tmpDir, opts)
108118
if err != nil {
109119
return nil, "", fmt.Errorf("unable to generate the injector payload configmaps: %w", err)
110120
}
@@ -118,7 +128,7 @@ func (c *Cluster) CreateInjectorConfigMaps(ctx context.Context, tmpDir, imagesDi
118128
"zarf-injector": b,
119129
}).
120130
WithLabels(map[string]string{
121-
PackageLabel: pkgName,
131+
PackageLabel: opts.PkgName,
122132
})
123133
_, err = c.Clientset.CoreV1().ConfigMaps(*cm.Namespace).Apply(ctx, cm, metav1.ApplyOptions{Force: true, FieldManager: FieldManagerName})
124134
if err != nil {
@@ -191,7 +201,7 @@ func (c *Cluster) StopInjection(ctx context.Context) error {
191201
return nil
192202
}
193203

194-
func (c *Cluster) createPayloadConfigMaps(ctx context.Context, tmpDir, imagesDir string, injectorSeedSrcs []string, pkgName string) ([]string, string, error) {
204+
func (c *Cluster) createPayloadConfigMaps(ctx context.Context, tmpDir string, opts InjectorOpts) ([]string, string, error) {
195205
l := logger.From(ctx)
196206
tarPath := filepath.Join(tmpDir, "payload.tar.gz")
197207
seedImagesDir := filepath.Join(tmpDir, "seed-images")
@@ -200,12 +210,12 @@ func (c *Cluster) createPayloadConfigMaps(ctx context.Context, tmpDir, imagesDir
200210
}
201211

202212
localReferenceToDigest := map[string]string{}
203-
for _, src := range injectorSeedSrcs {
213+
for _, src := range opts.InjectorSeedSrcs {
204214
ref, err := transform.ParseImageRef(src)
205215
if err != nil {
206216
return nil, "", fmt.Errorf("failed to create ref for image %s: %w", src, err)
207217
}
208-
img, err := utils.LoadOCIImage(imagesDir, ref)
218+
img, err := utils.LoadOCIImage(opts.ImagesDir, ref)
209219
if err != nil {
210220
return nil, "", err
211221
}
@@ -246,7 +256,7 @@ func (c *Cluster) createPayloadConfigMaps(ctx context.Context, tmpDir, imagesDir
246256
cm := v1ac.ConfigMap(fileName, state.ZarfNamespaceName).
247257
WithLabels(map[string]string{
248258
"zarf-injector": "payload",
249-
PackageLabel: pkgName,
259+
PackageLabel: opts.PkgName,
250260
}).
251261
WithBinaryData(map[string][]byte{
252262
fileName: data,
@@ -264,7 +274,7 @@ func (c *Cluster) createPayloadConfigMaps(ctx context.Context, tmpDir, imagesDir
264274
}
265275

266276
// getImagesAndNodesForInjection checks for images on schedulable nodes within a cluster.
267-
func (c *Cluster) getInjectorImageAndNode(ctx context.Context, resReq *v1ac.ResourceRequirementsApplyConfiguration) (string, string, error) {
277+
func (c *Cluster) getInjectorImageAndNode(ctx context.Context, resReq *v1ac.ResourceRequirementsApplyConfiguration, opts InjectorOpts) (string, string, error) {
268278
l := logger.From(ctx)
269279

270280
// List all nodes and running pods once
@@ -297,6 +307,10 @@ func (c *Cluster) getInjectorImageAndNode(ctx context.Context, resReq *v1ac.Reso
297307
continue
298308
}
299309

310+
if node.Status.NodeInfo.Architecture != "" && node.Status.NodeInfo.Architecture != opts.Architecture {
311+
continue
312+
}
313+
300314
availCPU := node.Status.Allocatable.Cpu().DeepCopy()
301315
availMem := node.Status.Allocatable.Memory().DeepCopy()
302316
var candidateImage string
@@ -486,7 +500,7 @@ func hasBlockingTaints(taints []corev1.Taint) bool {
486500
return false
487501
}
488502

489-
func buildInjectionPod(nodeName, image string, payloadCmNames []string, shasum string, resReq *v1ac.ResourceRequirementsApplyConfiguration, pkgName string) *v1ac.PodApplyConfiguration {
503+
func buildInjectionPod(nodeName, image string, payloadCmNames []string, shasum string, resReq *v1ac.ResourceRequirementsApplyConfiguration, opts InjectorOpts) *v1ac.PodApplyConfiguration {
490504
executeMode := int32(0777)
491505
userID := int64(1000)
492506
groupID := int64(2000)
@@ -530,7 +544,7 @@ func buildInjectionPod(nodeName, image string, payloadCmNames []string, shasum s
530544
WithLabels(map[string]string{
531545
"app": "zarf-injector",
532546
AgentLabel: "ignore",
533-
PackageLabel: pkgName,
547+
PackageLabel: opts.PkgName,
534548
}).
535549
WithSpec(
536550
v1ac.PodSpec().
@@ -548,6 +562,9 @@ func buildInjectionPod(nodeName, image string, payloadCmNames []string, shasum s
548562
WithType(corev1.SeccompProfileTypeRuntimeDefault),
549563
),
550564
).
565+
WithNodeSelector(map[string]string{
566+
"kubernetes.io/arch": opts.Architecture,
567+
}).
551568
WithContainers(
552569
v1ac.Container().
553570
WithName("injector").
@@ -583,14 +600,14 @@ func buildInjectionPod(nodeName, image string, payloadCmNames []string, shasum s
583600
}
584601

585602
// createInjectorNodeportService creates the injector service on an available port different than the registryNodePort service
586-
func (c *Cluster) createInjectorNodeportService(ctx context.Context, injectorNodePort, registryNodePort int, pkgName string) (*corev1.Service, error) {
603+
func (c *Cluster) createInjectorNodeportService(ctx context.Context, opts InjectorOpts) (*corev1.Service, error) {
587604
l := logger.From(ctx)
588605
var svc *corev1.Service
589606
timeoutCtx, cancel := context.WithTimeout(ctx, time.Second*30)
590607
defer cancel()
591608
portConfiguration := v1ac.ServicePort().WithPort(int32(5000))
592-
if injectorNodePort != 0 {
593-
portConfiguration.WithNodePort(int32(injectorNodePort))
609+
if opts.InjectorNodePort != 0 {
610+
portConfiguration.WithNodePort(int32(opts.InjectorNodePort))
594611
}
595612
err := retry.Do(func() error {
596613
svcAc := v1ac.Service("zarf-injector", state.ZarfNamespaceName).
@@ -601,7 +618,7 @@ func (c *Cluster) createInjectorNodeportService(ctx context.Context, injectorNod
601618
).WithSelector(map[string]string{
602619
"app": "zarf-injector",
603620
})).WithLabels(map[string]string{
604-
PackageLabel: pkgName,
621+
PackageLabel: opts.PkgName,
605622
})
606623

607624
var err error
@@ -611,13 +628,13 @@ func (c *Cluster) createInjectorNodeportService(ctx context.Context, injectorNod
611628
}
612629

613630
assignedNodePort := int(svc.Spec.Ports[0].NodePort)
614-
if assignedNodePort == registryNodePort {
631+
if assignedNodePort == opts.RegistryNodePort {
615632
l.Info("injector service NodePort conflicts with registry NodePort, recreating service", "conflictingPort", assignedNodePort)
616633
deleteErr := c.Clientset.CoreV1().Services(state.ZarfNamespaceName).Delete(ctx, "zarf-injector", metav1.DeleteOptions{})
617634
if deleteErr != nil {
618635
return deleteErr
619636
}
620-
return fmt.Errorf("nodePort conflict with registry port %d", registryNodePort)
637+
return fmt.Errorf("nodePort conflict with registry port %d", opts.RegistryNodePort)
621638
}
622639
return nil
623640
}, retry.Attempts(10), retry.Delay(500*time.Millisecond), retry.Context(timeoutCtx))

0 commit comments

Comments
 (0)