From 48f30b623853a3665178cbd1ece219d9a43397dc Mon Sep 17 00:00:00 2001 From: Andrew Gouin Date: Wed, 20 Sep 2023 09:27:38 -0600 Subject: [PATCH] feat(CosmosFullNode): Add image override (#355) --- .github/workflows/manifests.yaml | 22 +++++++++++++++++++ api/v1/cosmosfullnode_types.go | 4 ++++ .../cosmos.strange.love_cosmosfullnodes.yaml | 3 +++ internal/fullnode/build_pods.go | 20 ++++++++++++++--- internal/fullnode/build_pods_test.go | 21 ++++++++++++++++-- internal/fullnode/pod_builder.go | 7 ++++-- 6 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/manifests.yaml diff --git a/.github/workflows/manifests.yaml b/.github/workflows/manifests.yaml new file mode 100644 index 00000000..fd96a968 --- /dev/null +++ b/.github/workflows/manifests.yaml @@ -0,0 +1,22 @@ +name: Kube Manifests + +on: + push: + branches: + - main + pull_request: + +jobs: + verify: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 + with: + go-version: '>=1.20.2' + - run: make generate manifests + + - uses: CatChen/check-git-status-action@v1 + with: + fail-if-not-clean: true diff --git a/api/v1/cosmosfullnode_types.go b/api/v1/cosmosfullnode_types.go index 7e200ac5..0294a2d6 100644 --- a/api/v1/cosmosfullnode_types.go +++ b/api/v1/cosmosfullnode_types.go @@ -696,6 +696,10 @@ type InstanceOverridesSpec struct { // Overrides an individual instance's PVC. // +optional VolumeClaimTemplate *PersistentVolumeClaimSpec `json:"volumeClaimTemplate"` + + // Overrides an individual instance's Image. + // +optional + Image string `json:"image"` } type DisableStrategy string diff --git a/config/crd/bases/cosmos.strange.love_cosmosfullnodes.yaml b/config/crd/bases/cosmos.strange.love_cosmosfullnodes.yaml index eb870efb..f0b78e5b 100644 --- a/config/crd/bases/cosmos.strange.love_cosmosfullnodes.yaml +++ b/config/crd/bases/cosmos.strange.love_cosmosfullnodes.yaml @@ -312,6 +312,9 @@ spec: - Pod - All type: string + image: + description: Overrides an individual instance's Image. + type: string volumeClaimTemplate: description: Overrides an individual instance's PVC. properties: diff --git a/internal/fullnode/build_pods.go b/internal/fullnode/build_pods.go index 6b2fd069..c46571bb 100644 --- a/internal/fullnode/build_pods.go +++ b/internal/fullnode/build_pods.go @@ -22,18 +22,32 @@ func BuildPods(crd *cosmosv1.CosmosFullNode, cksums ConfigChecksums) ([]diff.Res if err != nil { return nil, err } - if disable := overrides[pod.Name].DisableStrategy; disable != nil { - continue - } if _, shouldSnapshot := candidates[pod.Name]; shouldSnapshot { continue } + if o, ok := overrides[pod.Name]; ok { + if o.DisableStrategy != nil { + continue + } + if o.Image != "" { + setMainContainerImage(pod, o.Image) + } + } pod.Annotations[configChecksumAnnotation] = cksums[client.ObjectKeyFromObject(pod)] pods = append(pods, diff.Adapt(pod, i)) } return pods, nil } +func setMainContainerImage(pod *corev1.Pod, image string) { + for i := range pod.Spec.Containers { + if pod.Spec.Containers[i].Name == mainContainer { + pod.Spec.Containers[i].Image = image + return + } + } +} + func podCandidates(crd *cosmosv1.CosmosFullNode) map[string]struct{} { candidates := make(map[string]struct{}) for _, v := range crd.Status.ScheduledSnapshotStatus { diff --git a/internal/fullnode/build_pods_test.go b/internal/fullnode/build_pods_test.go index 08369cac..bc93fcc9 100644 --- a/internal/fullnode/build_pods_test.go +++ b/internal/fullnode/build_pods_test.go @@ -60,15 +60,24 @@ func TestBuildPods(t *testing.T) { }) t.Run("instance overrides", func(t *testing.T) { + const ( + image = "agoric:latest" + overrideImage = "some_image:custom" + overridePod = "agoric-5" + ) crd := &cosmosv1.CosmosFullNode{ ObjectMeta: metav1.ObjectMeta{ Name: "agoric", }, Spec: cosmosv1.FullNodeSpec{ Replicas: 6, + PodTemplate: cosmosv1.PodSpec{ + Image: image, + }, InstanceOverrides: map[string]cosmosv1.InstanceOverridesSpec{ - "agoric-2": {DisableStrategy: ptr(cosmosv1.DisablePod)}, - "agoric-4": {DisableStrategy: ptr(cosmosv1.DisableAll)}, + "agoric-2": {DisableStrategy: ptr(cosmosv1.DisablePod)}, + "agoric-4": {DisableStrategy: ptr(cosmosv1.DisableAll)}, + overridePod: {Image: overrideImage}, }, }, } @@ -82,6 +91,14 @@ func TestBuildPods(t *testing.T) { }) got := lo.Map(pods, func(pod diff.Resource[*corev1.Pod], _ int) string { return pod.Object().Name }) require.Equal(t, want, got) + for _, pod := range pods { + image := pod.Object().Spec.Containers[0].Image + if pod.Object().Name == overridePod { + require.Equal(t, overrideImage, image) + } else { + require.Equal(t, image, image) + } + } }) t.Run("scheduled volume snapshot pod candidate", func(t *testing.T) { diff --git a/internal/fullnode/pod_builder.go b/internal/fullnode/pod_builder.go index 8f44b07f..67c77922 100644 --- a/internal/fullnode/pod_builder.go +++ b/internal/fullnode/pod_builder.go @@ -21,7 +21,10 @@ import ( var bufPool = sync.Pool{New: func() any { return new(bytes.Buffer) }} -const healthCheckPort = healthcheck.Port +const ( + healthCheckPort = healthcheck.Port + mainContainer = "node" +) // PodBuilder builds corev1.Pods type PodBuilder struct { @@ -65,7 +68,7 @@ func NewPodBuilder(crd *cosmosv1.CosmosFullNode) PodBuilder { Containers: []corev1.Container{ // Main start container. { - Name: "node", + Name: mainContainer, Image: tpl.Image, // The following is a useful hack if you need to inspect the PV. //Command: []string{"/bin/sh"},