diff --git a/CHANGELOG.md b/CHANGELOG.md index 51f6d17b1..59294ac01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - (Bugfix) (DP) Propagate Timeout Across Subcommands - (Maintenance) Bump Dependencies - (Feature) (Platform) EventsV1 Integration +- (Feature) (Platform) Allows to opt out in the Inventory Telemetry ## [1.3.1](https://github.com/arangodb/kube-arangodb/tree/1.3.1) (2025-10-07) - (Documentation) Add ArangoPlatformStorage Docs & Examples diff --git a/docs/cli/arangodb_operator_platform.md b/docs/cli/arangodb_operator_platform.md index 9b827fc76..4f8e5edfb 100644 --- a/docs/cli/arangodb_operator_platform.md +++ b/docs/cli/arangodb_operator_platform.md @@ -136,6 +136,7 @@ Flags: --arango.insecure Arango Endpoint Insecure --arango.token string Arango JWT Token for Authentication -h, --help help for inventory + --telemetry Enables Telemetry (default true) Global Flags: --kubeconfig string Kubernetes Config File @@ -165,6 +166,7 @@ Flags: --license.client.stage strings LicenseManager Stages (default [prd]) --license.endpoint string LicenseManager Endpoint (default "license.arango.ai") --license.interval duration Interval of the license synchronization + --telemetry Enables Telemetry (default true) Global Flags: --kubeconfig string Kubernetes Config File diff --git a/pkg/platform/flags.go b/pkg/platform/flags.go index 2ca528436..283d2fc76 100644 --- a/pkg/platform/flags.go +++ b/pkg/platform/flags.go @@ -170,6 +170,12 @@ var ( }, } + flagTelemetry = cli.Flag[bool]{ + Name: "telemetry", + Description: "Enables Telemetry", + Default: true, + } + flagRegistryUseCredentials = cli.Flag[bool]{ Name: "registry.docker.credentials", Description: "Use Docker Credentials", diff --git a/pkg/platform/inventory/aql.go b/pkg/platform/inventory/aql.go index 5133f8e7e..8fb46de0e 100644 --- a/pkg/platform/inventory/aql.go +++ b/pkg/platform/inventory/aql.go @@ -33,9 +33,25 @@ import ( ugrpc "github.com/arangodb/kube-arangodb/pkg/util/grpc" ) -func ExecuteAQL(db string, aql string, bind map[string]any) Executor { - return func(conn driver.Connection, out chan<- *Item) executor.RunFunc { +func ExecuteTelemetryAQL(db string, aql string, bind map[string]any) Executor { + return ExecuteAQL(db, aql, bind, true) +} + +func ExecuteBasicAQL(db string, aql string, bind map[string]any) Executor { + return ExecuteAQL(db, aql, bind, false) +} + +func ExecuteAQL(db string, aql string, bind map[string]any, telemetry bool) Executor { + return func(conn driver.Connection, cfg *Configuration, out chan<- *Item) executor.RunFunc { return func(ctx context.Context, log logging.Logger, t executor.Thread, h executor.Handler) error { + if telemetry { + if !cfg.WithTelemetry() { + log.Info("Telemetry disabled") + return nil + } + log.Info("Collecting Telemetry details") + } + c, err := driver.NewClient(driver.ClientConfig{Connection: async.NewConnectionAsyncWrapper(conn)}) if err != nil { return err diff --git a/pkg/platform/inventory/configuration.go b/pkg/platform/inventory/configuration.go new file mode 100644 index 000000000..2d37c2337 --- /dev/null +++ b/pkg/platform/inventory/configuration.go @@ -0,0 +1,32 @@ +// +// DISCLAIMER +// +// Copyright 2025 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. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// + +package inventory + +type Configuration struct { + Telemetry *bool +} + +func (c *Configuration) WithTelemetry() bool { + if c == nil || c.Telemetry == nil { + return true + } + return *c.Telemetry +} diff --git a/pkg/platform/inventory/fetcher.aql.timestamp.go b/pkg/platform/inventory/fetcher.aql.timestamp.go index 24b5a88b3..3d206bb8e 100644 --- a/pkg/platform/inventory/fetcher.aql.timestamp.go +++ b/pkg/platform/inventory/fetcher.aql.timestamp.go @@ -26,5 +26,5 @@ import _ "embed" var queryTimestampAQL string func init() { - global.MustRegister("aql.timestamp", ExecuteAQL("_system", queryTimestampAQL, nil)) + global.MustRegister("aql.timestamp", ExecuteBasicAQL("_system", queryTimestampAQL, nil)) } diff --git a/pkg/platform/inventory/fetcher.deployment.id.go b/pkg/platform/inventory/fetcher.deployment.id.go index ee6635ba1..0ac7a2370 100644 --- a/pkg/platform/inventory/fetcher.deployment.id.go +++ b/pkg/platform/inventory/fetcher.deployment.id.go @@ -35,7 +35,7 @@ import ( ) func init() { - global.MustRegister("deployment.id", func(conn driver.Connection, out chan<- *Item) executor.RunFunc { + global.MustRegister("deployment.id", func(conn driver.Connection, cfg *Configuration, out chan<- *Item) executor.RunFunc { return func(ctx context.Context, log logging.Logger, t executor.Thread, h executor.Handler) error { if handler := arangod.GetRequestWithTimeout[client.DeploymentID](ctx, globals.GetGlobals().Timeouts().ArangoD().Get(), conn, "_admin", "deployment", "id"); handler.Code() == goHttp.StatusOK { resp, err := handler.Response() diff --git a/pkg/platform/inventory/fetcher.server.mode.go b/pkg/platform/inventory/fetcher.server.mode.go index 59e5251f1..16342e021 100644 --- a/pkg/platform/inventory/fetcher.server.mode.go +++ b/pkg/platform/inventory/fetcher.server.mode.go @@ -34,7 +34,7 @@ import ( ) func init() { - global.MustRegister("server.mode", func(conn driver.Connection, out chan<- *Item) executor.RunFunc { + global.MustRegister("server.mode", func(conn driver.Connection, cfg *Configuration, out chan<- *Item) executor.RunFunc { return func(ctx context.Context, log logging.Logger, t executor.Thread, h executor.Handler) error { resp := arangod.GetRequestWithTimeout[driver.ClusterHealth](ctx, globals.GetGlobals().Timeouts().ArangoD().Get(), conn, "_admin", "cluster", "health") diff --git a/pkg/platform/inventory/fetcher.server.version.go b/pkg/platform/inventory/fetcher.server.version.go index 3fcc7d283..9969aaa4c 100644 --- a/pkg/platform/inventory/fetcher.server.version.go +++ b/pkg/platform/inventory/fetcher.server.version.go @@ -34,7 +34,7 @@ import ( ) func init() { - global.MustRegister("server.info", func(conn driver.Connection, out chan<- *Item) executor.RunFunc { + global.MustRegister("server.info", func(conn driver.Connection, cfg *Configuration, out chan<- *Item) executor.RunFunc { return func(ctx context.Context, log logging.Logger, t executor.Thread, h executor.Handler) error { resp, err := arangod.GetRequestWithTimeout[driver.VersionInfo](ctx, globals.GetGlobals().Timeouts().ArangoD().Get(), conn, "_api", "version"). AcceptCode(goHttp.StatusOK). diff --git a/pkg/platform/inventory/inventory.go b/pkg/platform/inventory/inventory.go index 51aec29b0..4840d7e27 100644 --- a/pkg/platform/inventory/inventory.go +++ b/pkg/platform/inventory/inventory.go @@ -33,7 +33,7 @@ import ( type Items []*Item -func FetchInventory(ctx context.Context, logger logging.Logger, threads int, conn driver.Connection) (Items, error) { +func FetchInventory(ctx context.Context, logger logging.Logger, threads int, conn driver.Connection, cfg *Configuration) (Items, error) { var out []*Item done := make(chan struct{}) in := make(chan *Item) @@ -50,7 +50,7 @@ func FetchInventory(ctx context.Context, logger logging.Logger, threads int, con } }() - if err := executor.Run(ctx, logger, threads, runExecution(conn, in)); err != nil { + if err := executor.Run(ctx, logger, threads, runExecution(conn, cfg, in)); err != nil { return nil, err } @@ -61,11 +61,11 @@ func FetchInventory(ctx context.Context, logger logging.Logger, threads int, con return out, nil } -func runExecution(conn driver.Connection, out chan<- *Item) executor.RunFunc { +func runExecution(conn driver.Connection, cfg *Configuration, out chan<- *Item) executor.RunFunc { return func(ctx context.Context, log logging.Logger, t executor.Thread, h executor.Handler) error { for _, executor := range global.Items() { log.Str("name", executor.K).Info("Starting executor") - q := executor.V(conn, out) + q := executor.V(conn, cfg, out) h.RunAsync(ctx, q) } @@ -76,7 +76,7 @@ func runExecution(conn driver.Connection, out chan<- *Item) executor.RunFunc { } } -type Executor func(conn driver.Connection, out chan<- *Item) executor.RunFunc +type Executor func(conn driver.Connection, cfg *Configuration, out chan<- *Item) executor.RunFunc func (i *Item) Validate() error { if i == nil { diff --git a/pkg/platform/license.go b/pkg/platform/license.go index 6cac81698..8f768d01a 100644 --- a/pkg/platform/license.go +++ b/pkg/platform/license.go @@ -73,9 +73,15 @@ func buildInventory(cmd *cobra.Command) (*inventory.Spec, error) { return nil, err } + var cfg inventory.Configuration + + if v, err := flagTelemetry.Get(cmd); err != nil || !v { + cfg.Telemetry = util.NewType(false) + } + logger.Info("Discovered Arango %s (%s)", resp.Version, resp.License) - obj, err := inventory.FetchInventory(cmd.Context(), logger, 8, conn) + obj, err := inventory.FetchInventory(cmd.Context(), logger, 8, conn, &cfg) if err != nil { return nil, err diff --git a/pkg/platform/license_activate.go b/pkg/platform/license_activate.go index f608b4783..c56a30a2f 100644 --- a/pkg/platform/license_activate.go +++ b/pkg/platform/license_activate.go @@ -39,7 +39,7 @@ func licenseActivate() (*cobra.Command, error) { cmd.Use = "activate" cmd.Short = "Activates the License on ArangoDB Endpoint" - if err := cli.RegisterFlags(&cmd, flagLicenseManager, flagActivateInterval, flagDeployment); err != nil { + if err := cli.RegisterFlags(&cmd, flagLicenseManager, flagActivateInterval, flagDeployment, flagTelemetry); err != nil { return nil, err } diff --git a/pkg/platform/license_inventory.go b/pkg/platform/license_inventory.go index 1ab78e859..a0e35b62a 100644 --- a/pkg/platform/license_inventory.go +++ b/pkg/platform/license_inventory.go @@ -36,7 +36,7 @@ func licenseInventory() (*cobra.Command, error) { cmd.Use = "inventory [flags] output" cmd.Short = "Inventory Generator" - if err := cli.RegisterFlags(&cmd, flagDeployment); err != nil { + if err := cli.RegisterFlags(&cmd, flagDeployment, flagTelemetry); err != nil { return nil, err }