diff --git a/docs/content/guides/alternative-datastore.md b/docs/content/guides/alternative-datastore.md index 414b124..1f11dd9 100644 --- a/docs/content/guides/alternative-datastore.md +++ b/docs/content/guides/alternative-datastore.md @@ -12,6 +12,29 @@ The following `make` recipes help you to setup alternative `Datastore` resources - **NATS**: `$ make -C deploy/kine/nats nats` +## Using a Custom Kine Image + +The default kine image can be overridden per-tenant by specifying a custom container image in the `additionalContainers` field: + +```yaml +apiVersion: kamaji.clastix.io/v1alpha1 +kind: TenantControlPlane +metadata: + name: tenant-name + namespace: kamaji-system +spec: + controlPlane: + deployment: + additionalContainers: + - name: kine + image: custom-kine-image:tag +``` + +This is useful for: +- Different database backends (postgresql, mysql, sqlite) +- Custom kine builds with specific features +- More granular control on a `TenantControlPlane` basis + !!! warning "Not for production" The default settings are not production grade: the following scripts are just used to test the Kamaji usage of different drivers. diff --git a/internal/builders/controlplane/deployment.go b/internal/builders/controlplane/deployment.go index d6aa116..49e6a8e 100644 --- a/internal/builders/controlplane/deployment.go +++ b/internal/builders/controlplane/deployment.go @@ -960,7 +960,9 @@ func (d Deployment) buildKine(podSpec *corev1.PodSpec, tcp kamajiv1alpha1.Tenant } podSpec.InitContainers[index].Name = kineInitContainerName - podSpec.InitContainers[index].Image = d.KineContainerImage + if podSpec.InitContainers[index].Image == "" { + podSpec.InitContainers[index].Image = d.KineContainerImage + } podSpec.InitContainers[index].Command = []string{"sh"} podSpec.InitContainers[index].Args = []string{ @@ -1019,7 +1021,9 @@ func (d Deployment) buildKine(podSpec *corev1.PodSpec, tcp kamajiv1alpha1.Tenant } podSpec.Containers[index].Name = kineContainerName - podSpec.Containers[index].Image = d.KineContainerImage + if podSpec.Containers[index].Image == "" { + podSpec.Containers[index].Image = d.KineContainerImage + } podSpec.Containers[index].Command = []string{"/bin/kine"} podSpec.Containers[index].Args = utilities.ArgsFromMapToSlice(args) podSpec.Containers[index].VolumeMounts = []corev1.VolumeMount{ diff --git a/internal/builders/controlplane/deployment_test.go b/internal/builders/controlplane/deployment_test.go index fd51e57..df8e0bc 100644 --- a/internal/builders/controlplane/deployment_test.go +++ b/internal/builders/controlplane/deployment_test.go @@ -12,6 +12,7 @@ import ( pointer "k8s.io/utils/ptr" kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1" + "github.com/clastix/kamaji/internal/utilities" ) func TestControlplaneDeployment(t *testing.T) { @@ -324,4 +325,68 @@ var _ = Describe("Controlplane Deployment", func() { Expect(*podSpec.AutomountServiceAccountToken).To(BeFalse()) }) }) + + Describe("Kine container image override", func() { + var tcp kamajiv1alpha1.TenantControlPlane + BeforeEach(func() { + d.KineContainerImage = "rancher/kine:v0.11.0" + d.DataStore = kamajiv1alpha1.DataStore{ + Spec: kamajiv1alpha1.DataStoreSpec{ + Driver: kamajiv1alpha1.KinePostgreSQLDriver, + }, + } + tcp = kamajiv1alpha1.TenantControlPlane{} + tcp.Status.Storage = kamajiv1alpha1.StorageStatus{ + Config: kamajiv1alpha1.DataStoreConfigStatus{ + SecretName: "test-secret", + }, + } + }) + + It("should use default kine image when not overridden", func() { + podSpec := &corev1.PodSpec{} + tcp.Spec.ControlPlane.Deployment.AdditionalContainers = []corev1.Container{} + + d.setAdditionalContainers(podSpec, tcp) + d.buildKine(podSpec, tcp) + + found, index := utilities.HasNamedContainer(podSpec.Containers, "kine") + Expect(found).To(BeTrue()) + Expect(podSpec.Containers[index].Image).To(Equal("rancher/kine:v0.11.0")) + }) + + It("should use custom kine image when overridden via additionalContainers", func() { + podSpec := &corev1.PodSpec{} + tcp.Spec.ControlPlane.Deployment.AdditionalContainers = []corev1.Container{ + { + Name: "kine", + Image: "my-custom-kine:v1.0.0", + }, + } + + d.setAdditionalContainers(podSpec, tcp) + d.buildKine(podSpec, tcp) + + found, index := utilities.HasNamedContainer(podSpec.Containers, "kine") + Expect(found).To(BeTrue()) + Expect(podSpec.Containers[index].Image).To(Equal("my-custom-kine:v1.0.0")) + }) + + It("should preserve custom kine container image when set via additionalContainers", func() { + podSpec := &corev1.PodSpec{} + tcp.Spec.ControlPlane.Deployment.AdditionalContainers = []corev1.Container{ + { + Name: "kine", + Image: "custom-kine:latest", + }, + } + + d.setAdditionalContainers(podSpec, tcp) + d.buildKine(podSpec, tcp) + + found, index := utilities.HasNamedContainer(podSpec.Containers, "kine") + Expect(found).To(BeTrue()) + Expect(podSpec.Containers[index].Image).To(Equal("custom-kine:latest")) + }) + }) })