diff --git a/CHANGELOG.md b/CHANGELOG.md index 92c97f34d..eb0c61302 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A) - (Feature) Extract Scheduler API +- (Bugfix) Fix Image Discovery ## [1.2.38](https://github.com/arangodb/kube-arangodb/tree/1.2.38) (2024-02-22) - (Feature) Extract GRPC Server diff --git a/chart/kube-arangodb/templates/deployment.yaml b/chart/kube-arangodb/templates/deployment.yaml index 7d16565dc..1350ce98e 100644 --- a/chart/kube-arangodb/templates/deployment.yaml +++ b/chart/kube-arangodb/templates/deployment.yaml @@ -132,6 +132,8 @@ spec: valueFrom: fieldRef: fieldPath: metadata.name + - name: MY_CONTAINER_NAME + value: "operator" - name: MY_POD_IP valueFrom: fieldRef: diff --git a/cmd/cmd.go b/cmd/cmd.go index 4933736e1..6058de8f0 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -46,6 +46,7 @@ import ( "k8s.io/client-go/tools/record" "github.com/arangodb/kube-arangodb/pkg/api" + shared "github.com/arangodb/kube-arangodb/pkg/apis/shared" "github.com/arangodb/kube-arangodb/pkg/crd" agencyConfig "github.com/arangodb/kube-arangodb/pkg/deployment/agency/config" "github.com/arangodb/kube-arangodb/pkg/deployment/features" @@ -594,13 +595,9 @@ func getMyPodInfo(kubecli kubernetes.Interface, namespace, name string) (string, return errors.WithStack(err) } sa = pod.Spec.ServiceAccountName - if image, err = k8sutil.GetArangoDBImageIDFromPod(pod); err != nil { + if image, err = k8sutil.GetArangoDBImageIDFromPod(pod, shared.ServerContainerName, shared.OperatorContainerName, constants.MyContainerNameEnv.GetOrDefault(shared.OperatorContainerName)); err != nil { return errors.Wrap(err, "failed to get image ID from pod") } - if image == "" { - // Fallback in case we don't know the id. - image = pod.Spec.Containers[0].Image - } return nil } if err := retry.Retry(op, time.Minute*5); err != nil { diff --git a/pkg/apis/shared/constants.go b/pkg/apis/shared/constants.go index 3edb99657..17c6e2eae 100644 --- a/pkg/apis/shared/constants.go +++ b/pkg/apis/shared/constants.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany +// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -45,6 +45,7 @@ const ( // Pod constants ServerContainerName = "server" ExporterContainerName = "exporter" + OperatorContainerName = "operator" ArangodVolumeName = "arangod-data" TlsKeyfileVolumeName = "tls-keyfile" ClientAuthCAVolumeName = "client-auth-ca" diff --git a/pkg/deployment/images.go b/pkg/deployment/images.go index b0684f88b..f2e0c4459 100644 --- a/pkg/deployment/images.go +++ b/pkg/deployment/images.go @@ -166,12 +166,8 @@ func (ib *imagesBuilder) fetchArangoDBImageIDAndVersion(ctx context.Context, cac return true, nil } - imageID, err := k8sutil.GetArangoDBImageIDFromPod(pod) - if err != nil { - log.Err(err).Warn("failed to get image ID from pod") - return true, nil - } - if imageID == "" { + imageID, ok := k8sutil.GetArangoDBImageIDFromContainerStatuses(pod.Status.ContainerStatuses, shared.ServerContainerName) + if !ok { // Fall back to specified image imageID = image } diff --git a/pkg/util/constants/constants.go b/pkg/util/constants/constants.go index b0b45f70c..b684ed57f 100644 --- a/pkg/util/constants/constants.go +++ b/pkg/util/constants/constants.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany +// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,6 +20,8 @@ package constants +import "github.com/arangodb/kube-arangodb/pkg/util" + const ( EnvOperatorNodeName = "MY_NODE_NAME" EnvOperatorNodeNameArango = "NODE_NAME" @@ -73,6 +75,10 @@ const ( LabelRoleLeader = "leader" ) +const ( + MyContainerNameEnv util.EnvironmentVariable = "MY_CONTAINER_NAME" +) + func ManagedFinalizers() []string { return []string{ FinalizerDeplRemoveChildFinalizers, diff --git a/pkg/util/k8sutil/container/container.go b/pkg/util/k8sutil/container/container.go index a764de9a7..db9ba532f 100644 --- a/pkg/util/k8sutil/container/container.go +++ b/pkg/util/k8sutil/container/container.go @@ -35,6 +35,17 @@ func GetContainerIDByName(containers []core.Container, name string) int { return -1 } +// GetContainerStatusIDByName returns the container id in the given list with the given name. +// // Returns -1 if not found. +func GetContainerStatusIDByName(containers []core.ContainerStatus, name string) int { + for id, c := range containers { + if c.Name == name { + return id + } + } + return -1 +} + // GetContainerByName returns the container in the given pod with the given name. // Returns false if not found. func GetContainerByName(p *core.Pod, name string) (core.Container, bool) { diff --git a/pkg/util/k8sutil/images.go b/pkg/util/k8sutil/images.go index b639ea5c2..5bcc89378 100644 --- a/pkg/util/k8sutil/images.go +++ b/pkg/util/k8sutil/images.go @@ -26,8 +26,8 @@ import ( core "k8s.io/api/core/v1" schedulerContainerResourcesApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1alpha1/container/resources" - shared "github.com/arangodb/kube-arangodb/pkg/apis/shared" "github.com/arangodb/kube-arangodb/pkg/util/errors" + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/container" ) const ( @@ -44,23 +44,53 @@ func ConvertImageID2Image(imageID string) string { } // GetArangoDBImageIDFromPod returns the ArangoDB specific image from a pod -func GetArangoDBImageIDFromPod(pod *core.Pod) (string, error) { +func GetArangoDBImageIDFromPod(pod *core.Pod, names ...string) (string, error) { if pod == nil { return "", errors.New("failed to get container statuses from nil pod") } - if len(pod.Status.ContainerStatuses) == 0 { - return "", errors.New("empty list of ContainerStatuses") + // First try to find container by name + if image, ok := GetArangoDBImageIDFromContainerStatuses(pod.Status.ContainerStatuses, names...); ok { + return image, nil } + if image, ok := GetArangoDBImageIDFromContainers(pod.Spec.Containers, names...); ok { + return image, nil + } + + if cs := pod.Status.ContainerStatuses; len(cs) > 0 { + if image := cs[0].ImageID; image != "" { + return ConvertImageID2Image(image), nil + } + } + if cs := pod.Spec.Containers; len(cs) > 0 { + if image := cs[0].Image; image != "" { + return image, nil + } + } + + return "", errors.Errorf("Unable to find image from pod") +} + +// GetArangoDBImageIDFromContainerStatuses returns the ArangoDB specific image from a container statuses +func GetArangoDBImageIDFromContainerStatuses(containers []core.ContainerStatus, names ...string) (string, bool) { + for _, name := range names { + if id := container.GetContainerStatusIDByName(containers, name); id != -1 { + return ConvertImageID2Image(containers[id].ImageID), true + } + } + + return "", false +} - for _, cs := range pod.Status.ContainerStatuses { - if cs.Name == shared.ServerContainerName { - return ConvertImageID2Image(cs.ImageID), nil +// GetArangoDBImageIDFromContainers returns the ArangoDB specific image from a container specs +func GetArangoDBImageIDFromContainers(containers []core.Container, names ...string) (string, bool) { + for _, name := range names { + if id := container.GetContainerIDByName(containers, name); id != -1 { + return containers[id].Image, true } } - // If Server container is not found use first container - return ConvertImageID2Image(pod.Status.ContainerStatuses[0].ImageID), nil + return "", false } // GetImageDetails Returns latest defined Image details diff --git a/pkg/util/k8sutil/images_test.go b/pkg/util/k8sutil/images_test.go index d3faba86f..07e0a39b1 100644 --- a/pkg/util/k8sutil/images_test.go +++ b/pkg/util/k8sutil/images_test.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany +// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -47,7 +47,7 @@ func TestGetArangoDBImageIDFromPod(t *testing.T) { args: args{ pod: &core.Pod{}, }, - wantErr: errors.New("empty list of ContainerStatuses"), + wantErr: errors.New("Unable to find image from pod"), }, "image ID from the only container": { args: args{ @@ -124,7 +124,7 @@ func TestGetArangoDBImageIDFromPod(t *testing.T) { for testName, testCase := range tests { t.Run(testName, func(t *testing.T) { - got, err := GetArangoDBImageIDFromPod(testCase.args.pod) + got, err := GetArangoDBImageIDFromPod(testCase.args.pod, shared.ServerContainerName) if testCase.wantErr != nil { require.EqualError(t, err, testCase.wantErr.Error()) return