diff --git a/CHANGELOG.md b/CHANGELOG.md index dccb7aad3..51d50abfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - (Refactor) Optimize go.mod entries - (Feature) Add `ArangoLocalStorage` CRD auto-installer - (Feature) Add `ArangoDeploymentReplication` CRD auto-installer +- (Bugfix) Allow missing `token` key in License secret ## [1.2.13](https://github.com/arangodb/kube-arangodb/tree/1.2.13) (2022-06-07) - (Bugfix) Fix arangosync members state inspection diff --git a/pkg/deployment/images.go b/pkg/deployment/images.go index a1e832484..24c44f21e 100644 --- a/pkg/deployment/images.go +++ b/pkg/deployment/images.go @@ -37,6 +37,7 @@ import ( "github.com/arangodb/kube-arangodb/pkg/deployment/resources" "github.com/arangodb/kube-arangodb/pkg/handlers/utils" "github.com/arangodb/kube-arangodb/pkg/logging" + "github.com/arangodb/kube-arangodb/pkg/util" "github.com/arangodb/kube-arangodb/pkg/util/arangod" "github.com/arangodb/kube-arangodb/pkg/util/constants" "github.com/arangodb/kube-arangodb/pkg/util/errors" @@ -66,7 +67,7 @@ type ContainerIdentity struct { // ArangoDIdentity helps to resolve the ArangoD identity, e.g.: image ID, version of the entrypoint. type ArangoDIdentity struct { interfaces.ContainerCreator - License api.LicenseSpec + License *string ipAddress string } @@ -214,6 +215,16 @@ func (ib *imagesBuilder) fetchArangoDBImageIDAndVersion(ctx context.Context, cac return false, nil } + // Find license + var license *string + if s := ib.Spec.License; s.HasSecretName() { + if secret, ok := cachedStatus.Secret().V1().GetSimple(s.GetSecretName()); ok { + if _, ok := secret.Data[constants.SecretKeyToken]; ok { + license = util.NewString(s.GetSecretName()) + } + } + } + imagePod := ImageUpdatePod{ spec: ib.Spec, apiObject: ib.APIObject, @@ -223,7 +234,7 @@ func (ib *imagesBuilder) fetchArangoDBImageIDAndVersion(ctx context.Context, cac image: image, imagePullPolicy: ib.Spec.GetImagePullPolicy(), }, - License: ib.Spec.License, + License: license, ipAddress: ib.Spec.GetListenAddr(), }, } @@ -443,9 +454,10 @@ func (a *ArangoDIdentity) GetArgs() ([]string, error) { func (a *ArangoDIdentity) GetEnvs() []core.EnvVar { env := make([]core.EnvVar, 0) - if a.License.HasSecretName() { + // Add advanced check for license + if l := a.License; l != nil { env = append(env, k8sutil.CreateEnvSecretKeySelector(constants.EnvArangoLicenseKey, - a.License.GetSecretName(), constants.SecretKeyToken)) + *l, constants.SecretKeyToken)) } if len(env) > 0 { diff --git a/pkg/deployment/images_test.go b/pkg/deployment/images_test.go index 360599885..0aa9d2ec0 100644 --- a/pkg/deployment/images_test.go +++ b/pkg/deployment/images_test.go @@ -32,8 +32,8 @@ import ( "github.com/arangodb/kube-arangodb/pkg/deployment/resources" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + core "k8s.io/api/core/v1" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/stretchr/testify/assert" @@ -54,7 +54,7 @@ type testCaseImageUpdate struct { After func(*testing.T, *Deployment) ExpectedError error RetrySoon bool - ExpectedPod v1.Pod + ExpectedPod core.Pod } func TestEnsureImages(t *testing.T) { @@ -82,29 +82,29 @@ func TestEnsureImages(t *testing.T) { }, }, RetrySoon: true, - ExpectedPod: v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ + ExpectedPod: core.Pod{ + Spec: core.PodSpec{ + Volumes: []core.Volume{ k8sutil.CreateVolumeEmptyDir(shared.ArangodVolumeName), }, - Containers: []v1.Container{ + Containers: []core.Container{ { Name: shared.ServerContainerName, Image: testNewImage, Command: createTestCommandForImageUpdatePod(), Ports: createTestPorts(), - Resources: v1.ResourceRequirements{ - Limits: make(v1.ResourceList), - Requests: make(v1.ResourceList), + Resources: core.ResourceRequirements{ + Limits: make(core.ResourceList), + Requests: make(core.ResourceList), }, - VolumeMounts: []v1.VolumeMount{ + VolumeMounts: []core.VolumeMount{ k8sutil.ArangodVolumeMount(), }, - ImagePullPolicy: v1.PullIfNotPresent, + ImagePullPolicy: core.PullIfNotPresent, SecurityContext: securityContext.NewSecurityContext(), }, }, - RestartPolicy: v1.RestartPolicyNever, + RestartPolicy: core.RestartPolicyNever, Tolerations: getTestTolerations(), TerminationGracePeriodSeconds: &terminationGracePeriodSeconds, Hostname: hostname, @@ -115,7 +115,23 @@ func TestEnsureImages(t *testing.T) { }, }, { - Name: "Image not been changed with license", + Before: func(t *testing.T, deployment *Deployment) { + c := deployment.acs.CurrentClusterCache() + + s := &core.Secret{ + ObjectMeta: meta.ObjectMeta{ + Name: testLicense, + Namespace: testNamespace, + }, + Data: map[string][]byte{ + constants.SecretKeyToken: []byte("data"), + }, + } + + _, err := c.SecretsModInterface().V1().Create(context.Background(), s, meta.CreateOptions{}) + require.NoError(t, err) + }, + Name: "Image not been changed with license (proper one)", ArangoDeployment: &api.ArangoDeployment{ Spec: api.DeploymentSpec{ Image: util.NewString(testNewImage), @@ -125,33 +141,132 @@ func TestEnsureImages(t *testing.T) { }, }, RetrySoon: true, - ExpectedPod: v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ + ExpectedPod: core.Pod{ + Spec: core.PodSpec{ + Volumes: []core.Volume{ k8sutil.CreateVolumeEmptyDir(shared.ArangodVolumeName), }, - Containers: []v1.Container{ + Containers: []core.Container{ { Name: shared.ServerContainerName, Image: testNewImage, Command: createTestCommandForImageUpdatePod(), Ports: createTestPorts(), - Env: []v1.EnvVar{ + Env: []core.EnvVar{ k8sutil.CreateEnvSecretKeySelector(constants.EnvArangoLicenseKey, testLicense, constants.SecretKeyToken), }, - Resources: v1.ResourceRequirements{ - Limits: make(v1.ResourceList), - Requests: make(v1.ResourceList), + Resources: core.ResourceRequirements{ + Limits: make(core.ResourceList), + Requests: make(core.ResourceList), + }, + VolumeMounts: []core.VolumeMount{ + k8sutil.ArangodVolumeMount(), + }, + ImagePullPolicy: core.PullIfNotPresent, + SecurityContext: securityContext.NewSecurityContext(), + }, + }, + RestartPolicy: core.RestartPolicyNever, + Tolerations: getTestTolerations(), + TerminationGracePeriodSeconds: &terminationGracePeriodSeconds, + Hostname: hostname, + Subdomain: testDeploymentName + "-int", + Affinity: k8sutil.CreateAffinity(testDeploymentName, + shared.ImageIDAndVersionRole, false, ""), + }, + }, + }, + { + Name: "Image not been changed with license (missing one)", + ArangoDeployment: &api.ArangoDeployment{ + Spec: api.DeploymentSpec{ + Image: util.NewString(testNewImage), + License: api.LicenseSpec{ + SecretName: util.NewString(testLicense), + }, + }, + }, + RetrySoon: true, + ExpectedPod: core.Pod{ + Spec: core.PodSpec{ + Volumes: []core.Volume{ + k8sutil.CreateVolumeEmptyDir(shared.ArangodVolumeName), + }, + Containers: []core.Container{ + { + Name: shared.ServerContainerName, + Image: testNewImage, + Command: createTestCommandForImageUpdatePod(), + Ports: createTestPorts(), + Resources: core.ResourceRequirements{ + Limits: make(core.ResourceList), + Requests: make(core.ResourceList), + }, + VolumeMounts: []core.VolumeMount{ + k8sutil.ArangodVolumeMount(), + }, + ImagePullPolicy: core.PullIfNotPresent, + SecurityContext: securityContext.NewSecurityContext(), + }, + }, + RestartPolicy: core.RestartPolicyNever, + Tolerations: getTestTolerations(), + TerminationGracePeriodSeconds: &terminationGracePeriodSeconds, + Hostname: hostname, + Subdomain: testDeploymentName + "-int", + Affinity: k8sutil.CreateAffinity(testDeploymentName, + shared.ImageIDAndVersionRole, false, ""), + }, + }, + }, + { + Before: func(t *testing.T, deployment *Deployment) { + c := deployment.acs.CurrentClusterCache() + + s := &core.Secret{ + ObjectMeta: meta.ObjectMeta{ + Name: testLicense, + Namespace: testNamespace, + }, + } + + _, err := c.SecretsModInterface().V1().Create(context.Background(), s, meta.CreateOptions{}) + require.NoError(t, err) + }, + Name: "Image not been changed with license (missing key)", + ArangoDeployment: &api.ArangoDeployment{ + Spec: api.DeploymentSpec{ + Image: util.NewString(testNewImage), + License: api.LicenseSpec{ + SecretName: util.NewString(testLicense), + }, + }, + }, + RetrySoon: true, + ExpectedPod: core.Pod{ + Spec: core.PodSpec{ + Volumes: []core.Volume{ + k8sutil.CreateVolumeEmptyDir(shared.ArangodVolumeName), + }, + Containers: []core.Container{ + { + Name: shared.ServerContainerName, + Image: testNewImage, + Command: createTestCommandForImageUpdatePod(), + Ports: createTestPorts(), + Resources: core.ResourceRequirements{ + Limits: make(core.ResourceList), + Requests: make(core.ResourceList), }, - VolumeMounts: []v1.VolumeMount{ + VolumeMounts: []core.VolumeMount{ k8sutil.ArangodVolumeMount(), }, - ImagePullPolicy: v1.PullIfNotPresent, + ImagePullPolicy: core.PullIfNotPresent, SecurityContext: securityContext.NewSecurityContext(), }, }, - RestartPolicy: v1.RestartPolicyNever, + RestartPolicy: core.RestartPolicyNever, Tolerations: getTestTolerations(), TerminationGracePeriodSeconds: &terminationGracePeriodSeconds, Hostname: hostname, @@ -169,18 +284,18 @@ func TestEnsureImages(t *testing.T) { }, }, Before: func(t *testing.T, deployment *Deployment) { - pod := v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ + pod := core.Pod{ + ObjectMeta: meta.ObjectMeta{ Name: k8sutil.CreatePodName(testDeploymentName, shared.ImageIDAndVersionRole, id, ""), - CreationTimestamp: metav1.Now(), + CreationTimestamp: meta.Now(), }, - Spec: v1.PodSpec{}, - Status: v1.PodStatus{ - Phase: v1.PodFailed, + Spec: core.PodSpec{}, + Status: core.PodStatus{ + Phase: core.PodFailed, }, } - _, err := deployment.PodsModInterface().Create(context.Background(), &pod, metav1.CreateOptions{}) + _, err := deployment.PodsModInterface().Create(context.Background(), &pod, meta.CreateOptions{}) require.NoError(t, err) }, After: func(t *testing.T, deployment *Deployment) { @@ -196,15 +311,15 @@ func TestEnsureImages(t *testing.T) { }, }, Before: func(t *testing.T, deployment *Deployment) { - pod := v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ + pod := core.Pod{ + ObjectMeta: meta.ObjectMeta{ Name: k8sutil.CreatePodName(testDeploymentName, shared.ImageIDAndVersionRole, id, ""), }, - Status: v1.PodStatus{ - Phase: v1.PodFailed, + Status: core.PodStatus{ + Phase: core.PodFailed, }, } - _, err := deployment.PodsModInterface().Create(context.Background(), &pod, metav1.CreateOptions{}) + _, err := deployment.PodsModInterface().Create(context.Background(), &pod, meta.CreateOptions{}) require.NoError(t, err) }, After: func(t *testing.T, deployment *Deployment) { @@ -221,19 +336,19 @@ func TestEnsureImages(t *testing.T) { }, RetrySoon: true, Before: func(t *testing.T, deployment *Deployment) { - pod := v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ + pod := core.Pod{ + ObjectMeta: meta.ObjectMeta{ Name: k8sutil.CreatePodName(testDeploymentName, shared.ImageIDAndVersionRole, id, ""), }, - Status: v1.PodStatus{ - Conditions: []v1.PodCondition{ + Status: core.PodStatus{ + Conditions: []core.PodCondition{ { - Type: v1.PodScheduled, + Type: core.PodScheduled, }, }, }, } - _, err := deployment.PodsModInterface().Create(context.Background(), &pod, metav1.CreateOptions{}) + _, err := deployment.PodsModInterface().Create(context.Background(), &pod, meta.CreateOptions{}) require.NoError(t, err) }, After: func(t *testing.T, deployment *Deployment) { @@ -250,20 +365,20 @@ func TestEnsureImages(t *testing.T) { }, RetrySoon: true, Before: func(t *testing.T, deployment *Deployment) { - pod := v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ + pod := core.Pod{ + ObjectMeta: meta.ObjectMeta{ Name: k8sutil.CreatePodName(testDeploymentName, shared.ImageIDAndVersionRole, id, ""), }, - Status: v1.PodStatus{ - Conditions: []v1.PodCondition{ + Status: core.PodStatus{ + Conditions: []core.PodCondition{ { - Type: v1.PodReady, - Status: v1.ConditionTrue, + Type: core.PodReady, + Status: core.ConditionTrue, }, }, }, } - _, err := deployment.PodsModInterface().Create(context.Background(), &pod, metav1.CreateOptions{}) + _, err := deployment.PodsModInterface().Create(context.Background(), &pod, meta.CreateOptions{}) require.NoError(t, err) }, After: func(t *testing.T, deployment *Deployment) { @@ -280,23 +395,23 @@ func TestEnsureImages(t *testing.T) { }, RetrySoon: true, Before: func(t *testing.T, deployment *Deployment) { - pod := v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ + pod := core.Pod{ + ObjectMeta: meta.ObjectMeta{ Name: k8sutil.CreatePodName(testDeploymentName, shared.ImageIDAndVersionRole, id, ""), }, - Status: v1.PodStatus{ - Conditions: []v1.PodCondition{ + Status: core.PodStatus{ + Conditions: []core.PodCondition{ { - Type: v1.PodReady, - Status: v1.ConditionTrue, + Type: core.PodReady, + Status: core.ConditionTrue, }, }, - ContainerStatuses: []v1.ContainerStatus{ + ContainerStatuses: []core.ContainerStatus{ {}, }, }, } - _, err := deployment.PodsModInterface().Create(context.Background(), &pod, metav1.CreateOptions{}) + _, err := deployment.PodsModInterface().Create(context.Background(), &pod, meta.CreateOptions{}) require.NoError(t, err) }, After: func(t *testing.T, deployment *Deployment) { @@ -322,7 +437,7 @@ func TestEnsureImages(t *testing.T) { } // Create custom resource in the fake kubernetes API - _, err := d.deps.Client.Arango().DatabaseV1().ArangoDeployments(testNamespace).Create(context.Background(), d.apiObject, metav1.CreateOptions{}) + _, err := d.deps.Client.Arango().DatabaseV1().ArangoDeployments(testNamespace).Create(context.Background(), d.apiObject, meta.CreateOptions{}) require.NoError(t, err) require.NoError(t, d.acs.CurrentClusterCache().Refresh(context.Background())) @@ -340,7 +455,7 @@ func TestEnsureImages(t *testing.T) { require.NoError(t, err) if len(testCase.ExpectedPod.Spec.Containers) > 0 { - pods, err := d.deps.Client.Kubernetes().CoreV1().Pods(testNamespace).List(context.Background(), metav1.ListOptions{}) + pods, err := d.deps.Client.Kubernetes().CoreV1().Pods(testNamespace).List(context.Background(), meta.ListOptions{}) require.NoError(t, err) require.Len(t, pods.Items, 1) require.Equal(t, testCase.ExpectedPod.Spec, pods.Items[0].Spec) @@ -368,14 +483,14 @@ func createTestCommandForImageUpdatePod() []string { } } -func getTestTolerations() []v1.Toleration { +func getTestTolerations() []core.Toleration { shortDur := k8sutil.TolerationDuration{ Forever: false, TimeSpan: time.Second * 5, } - return []v1.Toleration{ + return []core.Toleration{ k8sutil.NewNoExecuteToleration(k8sutil.TolerationKeyNodeNotReady, shortDur), k8sutil.NewNoExecuteToleration(k8sutil.TolerationKeyNodeUnreachable, shortDur), k8sutil.NewNoExecuteToleration(k8sutil.TolerationKeyNodeAlphaUnreachable, shortDur),