Skip to content

Commit 299caee

Browse files
authored
[Feature] Simplify Operator ID (#1981)
1 parent 9106a3f commit 299caee

33 files changed

+294
-162
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- (Maintenance) Bump Dependencies
99
- (Feature) (Platform) EventsV1 Integration
1010
- (Feature) (Platform) Allows to opt out in the Inventory Telemetry
11+
- (Feature) Simplify Operator ID Process
1112

1213
## [1.3.1](https://github.com/arangodb/kube-arangodb/tree/1.3.1) (2025-10-07)
1314
- (Documentation) Add ArangoPlatformStorage Docs & Examples

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,6 @@ Flags:
196196
--http1.transport.keep-alive-timeout-short duration Interval between keep-alive probes for an active network connection (default 100ms)
197197
--http1.transport.max-idle-conns int Maximum number of idle (keep-alive) connections across all hosts. Zero means no limit (default 100)
198198
--http1.transport.tls-handshake-timeout duration Maximum amount of time to wait for a TLS handshake. Zero means no timeout (default 10s)
199-
--image.discovery.status Discover Operator Image from Pod Status by default. When disabled Pod Spec is used. (default true)
200199
--image.discovery.timeout duration Timeout for image discovery process (default 1m0s)
201200
--internal.scaling-integration Enable Scaling Integration
202201
--kubernetes.burst int Burst for the k8s API (default 256)

cmd/cmd.go

Lines changed: 51 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ var (
162162
podSchedulingGracePeriod time.Duration
163163
}
164164
operatorImageDiscovery struct {
165-
timeout time.Duration
165+
timeout time.Duration
166+
// Deprecated: Do not use this flag, as discovery method changed
166167
defaultStatusDiscovery bool
167168
}
168169
operatorReconciliationRetry struct {
@@ -191,6 +192,12 @@ var (
191192
)
192193

193194
func init() {
195+
if err := initE(); err != nil {
196+
panic(err.Error())
197+
}
198+
}
199+
200+
func initE() error {
194201
var deprecatedStr string
195202

196203
f := cmdMain.Flags()
@@ -217,20 +224,14 @@ func init() {
217224
f.BoolVar(&operatorOptions.enablePlatform, "operator.platform", false, "Enable to run the Platform operator")
218225
f.BoolVar(&operatorOptions.enableScheduler, "operator.scheduler", false, "Enable to run the Scheduler operator")
219226
f.BoolVar(&operatorOptions.enableK2KClusterSync, "operator.k2k-cluster-sync", false, "Enable to run the ListSimple operator")
220-
f.MarkDeprecated("operator.k2k-cluster-sync", "Enabled within deployment operator")
221227
f.BoolVar(&operatorOptions.versionOnly, "operator.version", false, "Enable only version endpoint in Operator")
222228
f.StringVar(&deprecatedStr, "operator.alpine-image", "alpine:3.7", "Docker image used for alpine containers")
223-
f.MarkDeprecated("operator.alpine-image", "Value is not used anymore")
224229
f.StringVar(&deprecatedStr, "operator.metrics-exporter-image", "arangodb/arangodb-exporter:0.1.6", "Docker image used for metrics containers by default")
225-
f.MarkDeprecated("operator.metrics-exporter-image", "Value is not used anymore")
226230
f.StringVar(&deprecatedStr, "operator.arango-image", "arangodb/arangodb:latest", "Docker image used for arango by default")
227-
f.MarkDeprecated("operator.arango-image", "Value is not used anymore")
228231
f.BoolVar(&chaosOptions.allowed, "chaos.allowed", false, "Set to allow chaos in deployments. Only activated when allowed and enabled in deployment")
229232
f.BoolVar(&operatorOptions.skipLeaderLabel, "leader.label.skip", false, "Skips Leader Label for the Pod")
230233
f.BoolVar(&operatorOptions.singleMode, "mode.single", false, "Enable single mode in Operator. WARNING: There should be only one replica of Operator, otherwise Operator can take unexpected actions")
231234
f.String("scope", "", "Define scope on which Operator works. Legacy - pre 1.1.0 scope with limited cluster access")
232-
f.MarkDeprecated("scope", "Value is not used anymore")
233-
f.MarkHidden("scope")
234235
f.DurationVar(&operatorTimeouts.k8s, "timeout.k8s", globals.DefaultKubernetesTimeout, "The request timeout to the kubernetes")
235236
f.DurationVar(&operatorTimeouts.arangoD, "timeout.arangod", globals.DefaultArangoDTimeout, "The request timeout to the ArangoDB")
236237
f.DurationVar(&operatorTimeouts.arangoDCheck, "timeout.arangod-check", globals.DefaultArangoDCheckTimeout, "The version check request timeout to the ArangoDB")
@@ -257,24 +258,39 @@ func init() {
257258
f.IntVar(&operatorBackup.concurrentUploads, "backup-concurrent-uploads", globals.DefaultBackupConcurrentUploads, "Number of concurrent uploads per deployment")
258259
f.Uint64Var(&memoryLimit.hardLimit, "memory-limit", 0, "Define memory limit for hard shutdown and the dump of goroutines. Used for testing")
259260
f.StringArrayVar(&metricsOptions.excludedMetricPrefixes, "metrics.excluded-prefixes", nil, "List of the excluded metrics prefixes")
260-
f.BoolVar(&operatorImageDiscovery.defaultStatusDiscovery, "image.discovery.status", true, "Discover Operator Image from Pod Status by default. When disabled Pod Spec is used.")
261+
f.BoolVar(&operatorImageDiscovery.defaultStatusDiscovery, "image.discovery.status", true, "Image discovery method is now determined by the deployment's ImageDiscoveryMode specification")
261262
f.DurationVar(&operatorImageDiscovery.timeout, "image.discovery.timeout", time.Minute, "Timeout for image discovery process")
262263
f.IntVar(&threads, "threads", 16, "Number of the worker threads")
263-
if err := logging.Init(&cmdMain); err != nil {
264-
panic(err.Error())
265-
}
266-
if err := features.Init(&cmdMain); err != nil {
267-
panic(err.Error())
268-
}
269-
if err := agencyConfig.Init(&cmdMain); err != nil {
270-
panic(err.Error())
264+
265+
if err := errors.Errors(
266+
f.MarkDeprecated("operator.k2k-cluster-sync", "Enabled within deployment operator"),
267+
f.MarkDeprecated("operator.alpine-image", "Value is not used anymore"),
268+
f.MarkDeprecated("operator.metrics-exporter-image", "Value is not used anymore"),
269+
f.MarkDeprecated("operator.arango-image", "Value is not used anymore"),
270+
f.MarkDeprecated("scope", "Value is not used anymore"),
271+
f.MarkDeprecated("image.discovery.status", "Value fetched from the Operator Spec"),
272+
); err != nil {
273+
return errors.Wrap(err, "Unable to mark flags as deprecated")
271274
}
272-
if err := reconcile.ActionsConfigGlobal.Init(&cmdMain); err != nil {
273-
panic(err.Error())
275+
276+
if err := errors.Errors(
277+
f.MarkHidden("scope"),
278+
f.MarkHidden("image.discovery.status"),
279+
); err != nil {
280+
return errors.Wrap(err, "Unable to mark flags as hidden")
274281
}
275-
if err := operatorHTTP.InitConfiguration(&cmdMain); err != nil {
276-
panic(err.Error())
282+
283+
if err := errors.Errors(
284+
logging.Init(&cmdMain),
285+
features.Init(&cmdMain),
286+
agencyConfig.Init(&cmdMain),
287+
reconcile.ActionsConfigGlobal.Init(&cmdMain),
288+
operatorHTTP.InitConfiguration(&cmdMain),
289+
); err != nil {
290+
return errors.Wrap(err, "Unable to register secondary commands")
277291
}
292+
293+
return nil
278294
}
279295

280296
func Command() *cobra.Command {
@@ -590,7 +606,7 @@ func newOperatorConfigAndDeps(id, namespace, name string) (operator.Config, oper
590606
Namespace: namespace,
591607
PodName: name,
592608
ServiceAccount: serviceAccount,
593-
OperatorImage: image,
609+
Image: image,
594610
SkipLeaderLabel: operatorOptions.skipLeaderLabel,
595611
EnableDeployment: operatorOptions.enableDeployment,
596612
EnableDeploymentReplication: operatorOptions.enableDeploymentReplication,
@@ -633,18 +649,24 @@ func newOperatorConfigAndDeps(id, namespace, name string) (operator.Config, oper
633649

634650
// getMyPodInfo looks up the image & service account of the pod with given name in given namespace
635651
// Returns image, serviceAccount, error.
636-
func getMyPodInfo(kubecli kubernetes.Interface, namespace, name string) (string, string, error) {
637-
if image, sa, ok := getMyPodInfoWrap(kubecli, namespace, name, getMyImageInfoFunc(operatorImageDiscovery.defaultStatusDiscovery)); ok {
638-
return image, sa, nil
639-
}
652+
func getMyPodInfo(kubecli kubernetes.Interface, namespace, name string) (util.Image, string, error) {
653+
var ret util.Image
654+
var serviceAccount string
640655

641-
logger.Warn("Unable to discover image, fallback to second method")
656+
if image, sa, ok := getMyPodInfoWrap(kubecli, namespace, name, getMyImageInfoFunc(false)); !ok {
657+
return util.Image{}, "", errors.Errorf("Unable to discover Operator image from Spec")
658+
} else {
659+
ret.Image = image
660+
serviceAccount = sa
661+
}
642662

643-
if image, sa, ok := getMyPodInfoWrap(kubecli, namespace, name, getMyImageInfoFunc(!operatorImageDiscovery.defaultStatusDiscovery)); ok {
644-
return image, sa, nil
663+
if image, _, ok := getMyPodInfoWrap(kubecli, namespace, name, getMyImageInfoFunc(true)); ok {
664+
ret.StatusImage = util.NewType(image)
665+
} else {
666+
logger.Warn("Unable to discover image from status")
645667
}
646668

647-
return "", "", errors.Errorf("Unable to discover image")
669+
return ret, serviceAccount, nil
648670
}
649671

650672
func getMyPodInfoWrap(kubecli kubernetes.Interface, namespace, name string, imageFunc func(in *core.Pod) (string, bool)) (string, string, bool) {

cmd/cmd_pod_test.go

Lines changed: 73 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2025 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -41,49 +41,52 @@ func Test_PodDiscovery(t *testing.T) {
4141

4242
Pod core.Pod
4343

44-
Image, ServiceAccount string
44+
Image util.Image
4545

46-
Valid bool
46+
ServiceAccount string
4747

48-
DefaultStatusDiscovery *bool
48+
Valid bool
4949
}
5050

5151
var testCases = []testCase{
52+
//{
53+
// Name: "Empty pod",
54+
// Valid: false,
55+
//},
56+
//{
57+
// Name: "Not allowed containers",
58+
// Valid: false,
59+
// Pod: core.Pod{
60+
// ObjectMeta: meta.ObjectMeta{
61+
// Name: "operator",
62+
// Namespace: tests.FakeNamespace,
63+
// },
64+
// Spec: core.PodSpec{
65+
// Containers: []core.Container{
66+
// {
67+
// Name: "unknown",
68+
// Image: "image1",
69+
// },
70+
// },
71+
// },
72+
// Status: core.PodStatus{
73+
// ContainerStatuses: []core.ContainerStatus{
74+
// {
75+
// Name: "unknown",
76+
// Image: "image1",
77+
// ImageID: "image1",
78+
// },
79+
// },
80+
// },
81+
// },
82+
//},
5283
{
53-
Name: "Empty pod",
54-
Valid: false,
55-
},
56-
{
57-
Name: "Not allowed containers",
58-
Valid: false,
59-
Pod: core.Pod{
60-
ObjectMeta: meta.ObjectMeta{
61-
Name: "operator",
62-
Namespace: tests.FakeNamespace,
63-
},
64-
Spec: core.PodSpec{
65-
Containers: []core.Container{
66-
{
67-
Name: "unknown",
68-
Image: "image1",
69-
},
70-
},
71-
},
72-
Status: core.PodStatus{
73-
ContainerStatuses: []core.ContainerStatus{
74-
{
75-
Name: "unknown",
76-
Image: "image1",
77-
ImageID: "image1",
78-
},
79-
},
80-
},
84+
Name: "Allowed Status & Spec",
85+
Valid: true,
86+
Image: util.Image{
87+
Image: "image1",
88+
StatusImage: util.NewType("image1"),
8189
},
82-
},
83-
{
84-
Name: "Allowed Status & Spec",
85-
Valid: true,
86-
Image: "image1",
8790
ServiceAccount: "sa",
8891
Pod: core.Pod{
8992
ObjectMeta: meta.ObjectMeta{
@@ -111,9 +114,12 @@ func Test_PodDiscovery(t *testing.T) {
111114
},
112115
},
113116
{
114-
Name: "Allowed Status & Spec",
115-
Valid: true,
116-
Image: "imageStatusID1",
117+
Name: "Allowed Status & Spec",
118+
Valid: true,
119+
Image: util.Image{
120+
Image: "imageSpec1",
121+
StatusImage: util.NewType("imageStatusID1"),
122+
},
117123
ServiceAccount: "sa",
118124
Pod: core.Pod{
119125
ObjectMeta: meta.ObjectMeta{
@@ -141,11 +147,13 @@ func Test_PodDiscovery(t *testing.T) {
141147
},
142148
},
143149
{
144-
Name: "Allowed Status & Spec - From Spec",
145-
Valid: true,
146-
Image: "imageSpec1",
147-
ServiceAccount: "sa",
148-
DefaultStatusDiscovery: util.NewType(false),
150+
Name: "Allowed Status & Spec - From Spec",
151+
Valid: true,
152+
Image: util.Image{
153+
Image: "imageSpec1",
154+
StatusImage: util.NewType("imageStatusID1"),
155+
},
156+
ServiceAccount: "sa",
149157
Pod: core.Pod{
150158
ObjectMeta: meta.ObjectMeta{
151159
Name: "operator",
@@ -172,9 +180,11 @@ func Test_PodDiscovery(t *testing.T) {
172180
},
173181
},
174182
{
175-
Name: "Allowed Spec",
176-
Valid: true,
177-
Image: "imageSpec1",
183+
Name: "Allowed Spec",
184+
Valid: true,
185+
Image: util.Image{
186+
Image: "imageSpec1",
187+
},
178188
ServiceAccount: "sa",
179189
Pod: core.Pod{
180190
ObjectMeta: meta.ObjectMeta{
@@ -193,9 +203,12 @@ func Test_PodDiscovery(t *testing.T) {
193203
},
194204
},
195205
{
196-
Name: "Allowed Status & Spec - From Second Pod",
197-
Valid: true,
198-
Image: "imageStatusID2",
206+
Name: "Allowed Status & Spec - From Second Pod",
207+
Valid: true,
208+
Image: util.Image{
209+
Image: "imageSpec2",
210+
StatusImage: util.NewType("imageStatusID2"),
211+
},
199212
ServiceAccount: "sa",
200213
Pod: core.Pod{
201214
ObjectMeta: meta.ObjectMeta{
@@ -232,11 +245,13 @@ func Test_PodDiscovery(t *testing.T) {
232245
},
233246
},
234247
{
235-
Name: "Allowed Status & Spec - From Second Pod Spec",
236-
Valid: true,
237-
Image: "imageSpec2",
238-
ServiceAccount: "sa",
239-
DefaultStatusDiscovery: util.NewType(false),
248+
Name: "Allowed Status & Spec - From Second Pod Spec",
249+
Valid: true,
250+
Image: util.Image{
251+
Image: "imageSpec2",
252+
StatusImage: util.NewType("imageStatusID2"),
253+
},
254+
ServiceAccount: "sa",
240255
Pod: core.Pod{
241256
ObjectMeta: meta.ObjectMeta{
242257
Name: "operator",
@@ -275,8 +290,6 @@ func Test_PodDiscovery(t *testing.T) {
275290

276291
for _, testCase := range testCases {
277292
t.Run(testCase.Name, func(t *testing.T) {
278-
operatorImageDiscovery.defaultStatusDiscovery = util.TypeOrDefault(testCase.DefaultStatusDiscovery, true)
279-
280293
c := kclient.NewFakeClientBuilder().Add(&testCase.Pod).Client()
281294
image, sa, err := getMyPodInfo(c.Kubernetes(), tests.FakeNamespace, "operator")
282295

@@ -286,7 +299,8 @@ func Test_PodDiscovery(t *testing.T) {
286299
require.Empty(t, sa)
287300
} else {
288301
require.NoError(t, err)
289-
require.Equal(t, testCase.Image, image)
302+
require.Equal(t, testCase.Image.Image, image.Image)
303+
tests.EqualPointers(t, testCase.Image.StatusImage, image.StatusImage)
290304
require.Equal(t, testCase.ServiceAccount, sa)
291305
}
292306
})

docs/cli/arangodb_operator.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ Flags:
7878
--http1.transport.keep-alive-timeout-short duration Interval between keep-alive probes for an active network connection (default 100ms)
7979
--http1.transport.max-idle-conns int Maximum number of idle (keep-alive) connections across all hosts. Zero means no limit (default 100)
8080
--http1.transport.tls-handshake-timeout duration Maximum amount of time to wait for a TLS handshake. Zero means no timeout (default 10s)
81-
--image.discovery.status Discover Operator Image from Pod Status by default. When disabled Pod Spec is used. (default true)
8281
--image.discovery.timeout duration Timeout for image discovery process (default 1m0s)
8382
--internal.scaling-integration Enable Scaling Integration
8483
--kubernetes.burst int Burst for the k8s API (default 256)

integrations/scheduler/v2/suite_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/arangodb/kube-arangodb/pkg/logging"
3333
operator "github.com/arangodb/kube-arangodb/pkg/operatorV2"
3434
"github.com/arangodb/kube-arangodb/pkg/operatorV2/event"
35+
"github.com/arangodb/kube-arangodb/pkg/util"
3536
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil/helm"
3637
"github.com/arangodb/kube-arangodb/pkg/util/kclient"
3738
"github.com/arangodb/kube-arangodb/pkg/util/kclient/external"
@@ -102,7 +103,7 @@ func MockClient(t *testing.T, ctx context.Context, mods ...Mod) (pbSchedulerV2.S
102103
}
103104

104105
func chartHandler(client kclient.Client, ns string) operator.Handler {
105-
op := operator.NewOperator("mock", ns, "mock")
106+
op := operator.NewOperator("mock", ns, util.Image{Image: "mock"})
106107
recorder := event.NewEventRecorder("mock", client.Kubernetes())
107108

108109
return chart.Handler(op, recorder, client)

pkg/deployment/context_impl.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func (d *Deployment) GetServerGroupIterator() reconciler.ServerGroupIterator {
8484
}
8585

8686
func (d *Deployment) GetOperatorImage() string {
87-
return d.config.OperatorImage
87+
return d.config.Image.Get(d.GetSpec().ImageDiscoveryMode.Get() == api.DeploymentImageDiscoveryKubeletMode)
8888
}
8989

9090
// GetNamespace returns the kubernetes namespace that contains

pkg/deployment/deployment.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ type Config struct {
7171
ServiceAccount string
7272
AllowChaos bool
7373
ScalingIntegrationEnabled bool
74-
OperatorImage string
74+
Image util.Image
7575
ReconciliationDelay time.Duration
7676
}
7777

0 commit comments

Comments
 (0)